78

I've noticed that the Model.where method always returns an array even if there is only one result where as the Model.find method doesn't. Is there any reason for this? I thought Model.where was the preferred function since Rails 3.X.

Should I be using Model.find when I expect a single result and Model.where when I expect more than one result?

AdamB
  • 3,101
  • 4
  • 34
  • 44

3 Answers3

123
  • where returns an ActiveRecord::Relation (not an array, even though it behaves much like one), which is a collection of model objects. If nothing matches the conditions, it simply returns an empty relation.

  • find (and its related dynamic find_by_columnname methods) returns a single model object. If nothing is found, an ActiveRecord::RecordNotFound exception is raised (but not with the dynamic find_by_ methods).

    While find can return an Array of records—not a Relation—if given a list of IDs, using where is preferred since Rails 3. Many similar uses of find are now deprecated or gone entirely.

So yes, if you only want and expect a single object, using find is easier, as otherwise you must call Model.where.first.

Note that old-style hash options to find and many dynamic find_ methods are deprecated as of Rails 4.0 (see relevant release notes).

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
  • i think that `find` can return several objects in an array - try `User.find [1,2,3]` (finds users with ids 1, 2 and 3)... but yeah i guess andrew is right about the rest – klump Mar 05 '12 at 22:50
  • 3
    @klump Yup, it can, but `User.where(id: [1, 2, 3])` is preferred in that case so I didn't even consider it. As always I recommend reading the API documentation (which I've linked to in my answer), as it provides the most detail. – Andrew Marshall Mar 05 '12 at 22:55
  • But `.find(:all, ...)` returns an array. So what is the difference between find and where? – highBandWidth Oct 31 '12 at 20:53
  • @highBandWidth See above comments. I've also updated my answer. `where` doesn't return an Array (even though `Model.where(...).class` will lie and say it is). – Andrew Marshall Oct 31 '12 at 21:49
14

Actually find_by takes a model object from where obtained ActiveRecord::Relation

def find_by(*args)
  where(*args).take
end

Source

Kamil Lelonek
  • 14,592
  • 14
  • 66
  • 90
  • 4
    Note that find_by was not added until Rails 4 (original question was tagged rails 3). – Steve Jun 04 '14 at 21:23
7

Model.find is using the primary key column. Therefore there is always exactly one or no result. Use it when you are looking for one specific element identified by it's id.

iltempo
  • 15,718
  • 8
  • 61
  • 72