Reputation: 9764
I have a query, which works fine:
ModelName.where('true')
I can chain this with other AR calls such as where, order etc. However when I use:
ModelName.all
I receive the "same" response but can't chain a where or order to it as it's an array rather than a AR collection. Whereas I have no pragmatic problem using the first method it seems a bit ugly/unnecessary. Is there a cleaner way of doing this maybe a .to_active_record_collection or something?
Upvotes: 2
Views: 1039
Reputation: 115541
As you said:
ModelName.where('true').class #=> ActiveRecord::Relation
ModelName.all.class #=> Array
So you can make as many lazy loading as long as you don't use all
, first
or last
which trigger the query.
It's important to catch these differences when you consider caching.
Still I can't understand what kind of situation could lead you to something like:
ModelName.all.where(foobar)
... Unless you need the whole bunch of assets for one purpose and get it loaded from the database and need a subset of it to other purposes. For this kind of situation, you'd need to use ruby's Array filtering methods.
Sidenote:
ModelName.all
should never be used, it's an anti-pattern since you don' control how many items you'll retrieve. And hopefully:
ModelName.limit(20).class #=> ActiveRecord::Relation
Upvotes: 3
Reputation: 9764
There is an easy solution. Instead of using
ModelName.where('true')
Use:
ModelName.scoped
Upvotes: 5
Reputation: 7188
As you said, the latter returns an array of elements, while the former is an ActiveRecord::Relation
. You can order and filter array using Ruby methods. For example, to sort by id you can call sort_by(&:id)
. To filter elements you can call select
or reject
. For ActiveRecord::Relation
you can chain where
or order
to it, as you said.
The difference is where the sorting and processing goes. For Array, it is done by the application; for Relation - by the database. The latter is usually faster, when there is more records. It is also more memory efficient.
Upvotes: 1