Reputation: 359
I have been using
Product.allbut a lot of code that I have been seeing is using
Product.where(nil)when populating a variable. this site has an example that I found for using where(nil). I have searched through documentation and found where where(nil) replaced scoped but can't make heads or tails of what it does.
Upvotes: 6
Views: 1088
Reputation: 5562
I believe there used to be a difference, but from Rails 4 there no longer is. This is because from Rails 4 .all
returns a relation whereas it used to return an array. So previously:
Product.all
immediately fires a query to the database to return all records, which would get loaded into an array in memory. Basically you are telling Rails that you want the data NOW. See this question for more info.
Product.where(nil)
creates a query (actually an anonymous scope that returns an ActiveRecord:Relation
).
The query will only execute when you try to access the data for it. Since it is a scope, you can chain other scopes (without hitting the database each time) and have the entire chain execute as one query when you access the data.
In the Justin Weiss article linked to in the question, we see this code:
def index
@products = Product.where(nil) # creates an anonymous scope
@products = @products.status(params[:status]) if params[:status].present?
@products = @products.location(params[:location]) if params[:location].present?
@products = @products.starts_with(params[:starts_with]) if params[:starts_with].present?
end
That code will execute one database call when the index method ends and returns the data.
But if you changed the first line to:
@products = Product.all
that query would execute immediately. Then the scopes are added, and another query would fire when index method ends. This is more inefficient.
EDIT
I believe the database call would actually happen when you first try to access some data in @products (not when the index method ends). Eg. if you did @products.first then the query would execute.
Upvotes: 3