Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add relation#merge to merge two relations

  • Loading branch information...
commit a8b10a2a8d6f8d861453803264b9ef1b0cadbc6b 1 parent 08312e9
@lifo lifo authored
View
22 activerecord/lib/active_record/relation.rb
@@ -12,6 +12,18 @@ def initialize(klass, relation, readonly = false, preload = [], eager_load = [])
@loaded = false
end
+ def merge(r)
+ joins(r.relation.joins(r.relation)).
+ group(r.send(:group_clauses).join(', ')).
+ order(r.send(:order_clauses).join(', ')).
+ where(r.send(:where_clause)).
+ limit(r.taken).
+ offset(r.skipped).
+ select(r.send(:select_clauses).join(', '))
+ end
+
+ alias :& :merge
+
def preload(*associations)
create_new_relation(@relation, @readonly, @associations_to_preload + Array.wrap(associations))
end
@@ -25,7 +37,7 @@ def readonly
end
def select(selects)
- create_new_relation(@relation.project(selects))
+ selects.present? ? create_new_relation(@relation.project(selects)) : create_new_relation
end
# TODO : This is temporary. We need .from in Arel.
@@ -37,11 +49,11 @@ def from(from)
end
def group(groups)
- create_new_relation(@relation.group(groups))
+ groups.present? ? create_new_relation(@relation.group(groups)) : create_new_relation
end
def order(orders)
- create_new_relation(@relation.order(orders))
+ orders.present? ? create_new_relation(@relation.order(orders)) : create_new_relation
end
def reverse_order
@@ -57,11 +69,11 @@ def reverse_order
end
def limit(limits)
- create_new_relation(@relation.take(limits))
+ limits.present? ? create_new_relation(@relation.take(limits)) : create_new_relation
end
def offset(offsets)
- create_new_relation(@relation.skip(offsets))
+ offsets.present? ? create_new_relation(@relation.skip(offsets)) : create_new_relation
end
def on(join)
View
8 activerecord/test/cases/relations_test.rb
@@ -328,4 +328,12 @@ def test_destroy_all
assert davids.loaded?
end
+ def test_relation_merging
+ devs = Developer.where("salary >= 80000") & Developer.limit(2) & Developer.order('id ASC').where("id < 3")
+ assert_equal [developers(:david), developers(:jamis)], devs.to_a
+
+ dev_with_count = Developer.limit(1) & Developer.order('id DESC') & Developer.select('developers.*, count(id) id_count').group('id')
+ assert_equal [developers(:poor_jamis)], dev_with_count.to_a
+ assert_equal 1, dev_with_count.first.id_count.to_i
+ end
end

2 comments on commit a8b10a2

@ncr

cool!

@KieranP

Might cause issues if you do this:

Developer.where("salary >= 80000") & User.where(:name => 'lifo')

Some exception handling would be good.

Please sign in to comment.
Something went wrong with that request. Please try again.