Reputation: 5400
What is the difference in the objects created with these 2 methods:
tec = Technique.find(6)
tec2 = Technique.where(:korean => 'Jok Sul')
The data returned for each is exactly the same, yet the first object will respond perfectly to an inherited method like update_attributes while the second object will give an error of method not found.
When I do tec.class and tec2.class one is an ActiveRecord::Relation and the other doesn't give me a class at all, it just prints out the content of the object.
Maybe when you use the .where method you get an array, even if there is only one match and therefore you always have to issue the .each method to get at the contents? But that makes it hard to deal with when you want to update records, etc.
Can someone clarify this for me? Specifically, how to deal with matches found through the .where method.
Thanks.
Upvotes: 0
Views: 403
Reputation: 33954
The find(6)
returns a single object, because you're specifying the object ID in the database, which is guaranteed to be unique by convention.
The where
call returns a collection, which may be only 1 item long, but it still returns a collection, not a single object.
You can reveal this difference. Using your example code, if you call tec.class
vs. tec2.class
I think you'll find that they aren't the same class of object, as you expect.
That is, the methods available to a collection of objects is different than the methods available on an instance of that object.
Upvotes: 1
Reputation: 13433
Good question.
tec_scope = Technique.where(:korean => 'Jok Sul') # create an internal query
Remember, here only the query is created, it is not executed. You can programmatically build on top of this query if you so wished. The scope (or query if you so wish) will be executed in 2 ways. "Implicit" or "Explicit". Implicit way of running the query happens for example in the console, which invokes a method on the scope which automatically runs the query for you. This wont happen in your controllers unless you run it explicitly for .e.g
tec_scope.all # returns array
tec_scope.first # retuns one element
Scopes are just adding where clauses/predicates to your query. It's query building and delaying the execution till it is needed.
However,
tec_objects = Technique.find(6) # explicitly runs a query and returns one object (in this case)
This will explicitly run the query there and then. It is a question of the timing of execution of the query.
The difference is subtle but very important.
This hasnt got anything to do with whether you get one result or an array.
Technique.find([4,5]) # will return an array
Technique.find(4) # will return one object
Technique.where(:some_key => "some value").all # will return an array
Technique.where(:id => 5).first # will return one object
The difference is in timing of the execution of the query. Don't let the console fool you into believing there is no difference. Console is implicitly firing the query for you :)
Upvotes: 2
Reputation: 5878
Try:
tec2 = Technique.where(:korean => 'Jok Sul').first
Upvotes: 2