31

Using Arel in Rails - I'm looking for a way of creating an ActiveRecord::Relation that effectively results in SELECT * FROM table, which I can still manipulate further.

For example, I have a model that's split up into multiple categories, and I return counts for these in the following manner:

relation = Model.where(:archived => false) # all non-archived records
record_counts = {
  :total => relation.count,
  :for_sale => relation.where(:for_sale => true).count
  :on_auction => relation.where(:on_auction => true).count
}

This works fine, and has the advantage of firing off COUNT queries to MySQL, rather than actually selecting the records themselves.

However, I now need to include archived records in the counts, but relation = Model.all results in an Array, and I'm looking for an ActiveRecord::Relation.

The only way I can think of doing this is model.where(model.arel_table[:id].not_eq(nil)), which works, but seems slightly absurd.

Can anyone shed any light on this?

Jeriko
  • 6,547
  • 4
  • 28
  • 40

3 Answers3

48

Try relation = Model.scoped. That will give you the relation instead of the actual results.

Dylan Markow
  • 123,080
  • 26
  • 284
  • 201
12

For Rails 4.1 and above: Model.all returns a relation (where it previously did not)

For Rails 4.0: Model.where(nil)

For Rails 3.x: Model.scoped

Kyle Heironimus
  • 7,741
  • 7
  • 39
  • 51
1

You would want:

relation = Model.scoped

which if you see what relation is, it is in fact an ActiveRecord::Relation.

As you can see from this page:

http://api.rubyonrails.org/classes/ActiveRecord/NamedScope/ClassMethods.html#method-i-scoped

It says the following:

Anonymous scopes tend to be useful when procedurally generating complex queries, where passing intermediate values (scopes) around as first-class objects is convenient.

Mike Lewis
  • 63,433
  • 20
  • 141
  • 111
  • The only time `scoped` is really necessary is when you want to act on all of the records, like `Model.all`. Just doing a `Model.where(:archived => false)` will already just return an `ActiveRecord::Relation` object. – Dylan Markow Apr 08 '11 at 13:54