I’m a PHP developer learning the awesomness of Ruby on Rails, I’m loving ActiveRecord and i noticed something really interesting, Which is how ActiveRecord methods detect the end of method chain to execute the query.
@person = Person.where(name: 'Jason').where(age: 26)
# In my humble imagination I'd think that each where() executes a database query
# But in reality, it doesn't until the last method in the chain
How does this sorcery work?
The
wheremethod returns anActiveRecord::Relationobject, and by itself this object does not issue a database query. It’s where you use this object that matters.In the console, you’re probably doing this:
And then blammo it issues a database query and returns what appears to be an array of everyone named Jason. Yay, Active Record!
But then you do something like this:
And then that issues another query, but this one’s for people who are called Jason who are 26. But it’s only issuing one query, so where’d the other query go?
As others have suggested, this is happening because the
wheremethod returns a proxy object. It doesn’t actually perform a query and return a dataset unless it’s asked to do that.When you run anything in the console, it’s going to output the inspected version of the outcome of whatever it is you ran. If you put
1in the console and hit enter, you’ll get1back because1.inspectis1. Magic! Same goes for"1". A variety of other objects don’t have aninspectmethod defined and so Ruby falls back to the one onObjectwhich returns something ghastly like<Object#23adbf42560>.Every single
ActiveRecord::Relationobject has theinspectmethod defined on it so that it causes a query. When you write the query in your console, IRB will callinspecton the return value from that query and output something almost human readable, like the Array that you’d see.If you were just issuing this in a standard Ruby script, then no query would be executed until the object was inspected (via
inspect) or was iterated through usingeach, or had theto_amethod called on it.Up until one of those three things happen, you can chain as many
wherestatements on it as you will like and then when you do callinspect,to_aoreachon it, then it will finally execute that query.