Hi I''m trying to understand the AR find facilities, described here: http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M000650 I have a list of ids that I want to retrieve, but have a condition that should restrict the list returned: return self.find( noteids, :conditions => [ "(private = 0 OR (private = 1 AND user_id = ?))", userid] ) According to the documentation for find, I can supply this list of noteids and a :conditions option. I can see in the developer log that this results in an SQL call like this: SELECT * FROM notes WHERE notes.id IN (''17'',''36'',''39'',''54'') AND (private = 0 OR (private = 1 AND user_id = 1)) ORDER BY id But when the conditions supplied reduce the actual number of notes returned (e.g. the note with id 54 is excluded) then I get an ActiveRecord::RecordNotFound, which is raised in active_record/base.rb line 356: if result.size == ids.size return result else raise RecordNotFound, "Couldn''t find all #{name.pluralize} with IDs (#{ids_list})#{conditions}" end (I have active record version 1.10.1) The ability to supply a :conditions option in the find (by id) call seems to conflict with the code above - any condition that would exclude something with a given (supplied) id would cause this RecordNotFound issue. It''s likely that it''s my misunderstanding, so I''d be grateful for any enlightenment please. Thanks! DJ Adams p.s. I''ve Googled in vain for this so far ...
BigSmoke
2005-Jul-01 22:04 UTC
Re: Find by ID plus conditions -> ActiveRecord::RecordNotFound
On 6/30/05, DJ Adams <dj.adams-e+AXbWqSrlAAvxtiuMwx3w@public.gmane.org> wrote:> Hi > > I''m trying to understand the AR find facilities, described here: > http://api.rubyonrails.com/classes/ActiveRecord/Base.html#M000650 > > I have a list of ids that I want to retrieve, but have a condition that > should restrict the list returned: > > return self.find( > noteids, > :conditions => [ "(private = 0 OR (private = 1 AND user_id = ?))", userid] > ) > > According to the documentation for find, I can supply this list of > noteids and a :conditions option. > > I can see in the developer log that this results in an SQL call like > this: > > SELECT * FROM notes WHERE notes.id IN (''17'',''36'',''39'',''54'') AND (private = 0 OR (private = 1 AND user_id = 1)) ORDER BY id > > But when the conditions supplied reduce the actual number of notes > returned (e.g. the note with id 54 is excluded) then I get an > ActiveRecord::RecordNotFound, which is raised in active_record/base.rb > line 356: > > if result.size == ids.size > return result > else > raise RecordNotFound, "Couldn''t find all #{name.pluralize} with IDs (#{ids_list})#{conditions}" > end > > (I have active record version 1.10.1) > > The ability to supply a :conditions option in the find (by id) call > seems to conflict with the code above - any condition that would exclude > something with a given (supplied) id would cause this RecordNotFound > issue.>From the API docs:Find operates with three different retreval approaches: * Find by id: This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). If no record can be found for all of the listed ids, then RecordNotFound will be raised. * Find first: This will return the first record matched by the options used. These options can either be specific conditions or merely an order. If no record can matched, nil is returned. * Find all: This will return all the records matched by the options used. If no records are found, an empty array is returned. Perhaps you should try return self.find( :all, noteids, :conditions => [ "(private = 0 OR (private = 1 AND user_id = ?))", userid] ) The if-statement you analized actually occurs within the else block of a case-statement. The second when-block (when :all on line 333) is what will be used if you try my example. You might also want to take a look at more examples in http://api.rubyonrails.com/ I hope this helps, - Rowan -- Morality is usually taught by the immoral.
DJ Adams
2005-Jul-04 07:30 UTC
Re: Find by ID plus conditions -> ActiveRecord::RecordNotFound
On Sat, Jul 02, 2005 at 12:04:58AM +0200, BigSmoke wrote:> >From the API docs: > > Find operates with three different retreval approaches: > * Find by id: This can either be a specific id (1), a list of ids (1, 5, 6), > or an array of ids ([5, 6, 10]). If no record can be found for > all of the listed > ids, then RecordNotFound will be raised. > [...]Hi Rowan Thanks for your response, it''s appreciated. I did read the API documentation, and that''s what led me to ask the question. Basically it boils down to: "Why allow a condition on find-by-id and then raise an exception if that condition does what you want - filtering the records found from the list of IDs supplied?" It just doesn''t make sense, unless you''re writing exception-driven code (which I don''t think is the case). In other words, I have a list of IDs that I want to pick from, and I only want those that satisfy the condition. That seems a reasonable thing to want to do. But trying that results in an exception. Using the :all construct (which I did in the end, and which you showed as a workaround) does do the job, but is ultimately more ''blunt''. Thanks DJ