Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

adding two ActiveRecord::Relation objects [duplicate]

How do you add two relations together? When I try the + operator it returns an array. But I need it to return a relation.

thanks, mike

like image 367
Mike Glaz Avatar asked Sep 06 '12 04:09

Mike Glaz


People also ask

What is an ActiveRecord relation object?

An instance of ActiveRecord::Base is an object that represents a specific row of your database (or might be saved into the database). Whereas an instance of ActiveRecord::Relation is a representation of a query that can be run against your database (but wasn't run yet).

How do you duplicate an object in Rails?

You generally use #clone if you want to copy an object including its internal state. This is what Rails is using with its #dup method on ActiveRecord. It uses #dup to allow you to duplicate a record without its "internal" state (id and timestamps), and leaves #clone up to Ruby to implement.

What does ActiveRecord where return?

Returns a new relation, which is the result of filtering the current relation according to the conditions in the arguments.


3 Answers

Try:

new_relation = relation.merge(another_relation)
like image 81
xdazz Avatar answered Nov 15 '22 18:11

xdazz


You can add two ActiveRecord::Relation with Arel Constraints

constraints_1 = Model.matching_one.arel.constraints
constraints_2 = Model.matching_two.arel.constraints

Model.where(constraints_1.and(constraints_2)).class => ActiveRecord::Relation

You can use or operator too

Model.where(constraints_1.or(constraints_2)).class => ActiveRecord::Relation

Real example

constraints_1 = User.where(id: 1..5).arel.constraints
constraints_2 = User.where('id != 2').arel.constraints

User.where(constraints_1.and(constraints_2))

You can watch excellent screen cast about that http://railscasts.com/episodes/355-hacking-with-arel

like image 41
Joel AZEMAR Avatar answered Nov 15 '22 20:11

Joel AZEMAR


If you are adding ActiveRecord::Relation objects to get an 'OR' result rather than 'AND' (you'd get 'AND' behavior by chaining), and you still need the result to be an ActiveRecord::Relation to play nice with some other code (meta_search, for example)....

def matching_one_or_two
  temp = Model.matching_one + Model.matching_two
  Model.where('id in (?)',temp.map(&:id))
end

Certainly not the world's greatest performance, but it results in an ActiveRecord::Relation object pointing at the 'OR' results.

You can also just put the "OR" directly into the sql, rather than asking Rails to generate it for you, to give your database application a chance to perform better. One example:

Model.where("table_name.col = 'one' OR table_name.col = 'two'")

That will also return an ActiveRecord::Relation object.

like image 24
Anatortoise House Avatar answered Nov 15 '22 19:11

Anatortoise House