From 08312e9958b84de9aef07ba157eed04750567da4 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sun, 27 Dec 2009 23:29:38 +0530 Subject: Return a new relation when blank is supplied to relation.joins --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 4aa460a601..d1f4dc2101 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -69,7 +69,7 @@ module ActiveRecord end def joins(join, join_type = nil) - return self if join.blank? + return create_new_relation if join.blank? join_relation = case join when String -- cgit v1.2.3 From a8b10a2a8d6f8d861453803264b9ef1b0cadbc6b Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 28 Dec 2009 01:08:34 +0530 Subject: Add relation#merge to merge two relations --- activerecord/lib/active_record/relation.rb | 22 +++++++++++++++++----- activerecord/test/cases/relations_test.rb | 8 ++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index d1f4dc2101..967e429fc3 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -12,6 +12,18 @@ module ActiveRecord @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 @@ module ActiveRecord 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 @@ module ActiveRecord 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 @@ module ActiveRecord 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) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 2ec8c0d3a2..c639fb978d 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -328,4 +328,12 @@ class RelationTest < ActiveRecord::TestCase 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 -- cgit v1.2.3 From 51a1d5a6708726ae03deb5869f36e7d5cca22a6e Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 28 Dec 2009 01:33:20 +0530 Subject: Handle preloads and eager loads when merging relations --- activerecord/lib/active_record/relation.rb | 6 ++++-- activerecord/test/cases/relations_test.rb | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 967e429fc3..d0f6c5a63f 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -2,7 +2,7 @@ module ActiveRecord class Relation delegate :to_sql, :to => :relation delegate :length, :collect, :find, :map, :each, :to => :to_a - attr_reader :relation, :klass + attr_reader :relation, :klass, :associations_to_preload, :eager_load_associations def initialize(klass, relation, readonly = false, preload = [], eager_load = []) @klass, @relation = klass, relation @@ -19,7 +19,9 @@ module ActiveRecord where(r.send(:where_clause)). limit(r.taken). offset(r.skipped). - select(r.send(:select_clauses).join(', ')) + select(r.send(:select_clauses).join(', ')). + eager_load(r.eager_load_associations). + preload(r.associations_to_preload) end alias :& :merge diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index c639fb978d..0644db362a 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -332,8 +332,24 @@ class RelationTest < ActiveRecord::TestCase 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') + dev_with_count = Developer.limit(1) & Developer.order('id DESC') & Developer.select('developers.*').group('id') assert_equal [developers(:poor_jamis)], dev_with_count.to_a - assert_equal 1, dev_with_count.first.id_count.to_i + end + + def test_relation_merging_with_eager_load + relations = [] + relations << (Post.order('comments.id DESC') & Post.eager_load(:last_comment) & Post.scoped) + relations << (Post.eager_load(:last_comment) & Post.order('comments.id DESC') & Post.scoped) + + relations.each do |posts| + post = posts.find { |p| p.id == 1 } + assert_equal Post.find(1).last_comment, post.last_comment + end + end + + def test_relation_merging_with_preload + [Post.scoped & Post.preload(:author), Post.preload(:author) & Post.scoped].each do |posts| + assert_queries(2) { assert posts.first.author } + end end end -- cgit v1.2.3 From 630dc5073075ba73251400400caae802f8d97d41 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 28 Dec 2009 02:50:04 +0530 Subject: Fix relation tests for postgres --- activerecord/test/cases/relations_test.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'activerecord') diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 0644db362a..61fcc7ca46 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -38,7 +38,7 @@ class RelationTest < ActiveRecord::TestCase end def test_scoped_first - topics = Topic.scoped + topics = Topic.scoped.order('id ASC') assert_queries(1) do 2.times { assert_equal "The First Topic", topics.first.title } @@ -48,7 +48,7 @@ class RelationTest < ActiveRecord::TestCase end def test_loaded_first - topics = Topic.scoped + topics = Topic.scoped.order('id ASC') assert_queries(1) do topics.all # force load @@ -244,7 +244,7 @@ class RelationTest < ActiveRecord::TestCase author = Author.scoped.find_by_id!(authors(:david).id) assert_equal "David", author.name - assert_raises(ActiveRecord::RecordNotFound) { Author.scoped.find_by_id_and_name!('invalid', 'wt') } + assert_raises(ActiveRecord::RecordNotFound) { Author.scoped.find_by_id_and_name!(20, 'invalid') } end def test_dynamic_find_all_by_attributes @@ -281,7 +281,7 @@ class RelationTest < ActiveRecord::TestCase david = authors.find(authors(:david).id) assert_equal 'David', david.name - assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('invalid') } + assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find('42') } end def test_find_ids @@ -294,8 +294,8 @@ class RelationTest < ActiveRecord::TestCase assert_equal 'Mary', results[1].name assert_equal results, authors.find([authors(:david).id, authors(:mary).id]) - assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, 'invalid') } - assert_raises(ActiveRecord::RecordNotFound) { authors.find(['invalid', 'oops']) } + assert_raises(ActiveRecord::RecordNotFound) { authors.where(:name => 'lifo').find(authors(:david).id, '42') } + assert_raises(ActiveRecord::RecordNotFound) { authors.find(['42', 43]) } end def test_exists @@ -303,7 +303,8 @@ class RelationTest < ActiveRecord::TestCase assert davids.exists? assert davids.exists?(authors(:david).id) assert ! davids.exists?(authors(:mary).id) - assert ! davids.exists?("hax'id") + assert ! davids.exists?("42") + assert ! davids.exists?(42) fake = Author.where(:name => 'fake author') assert ! fake.exists? @@ -332,7 +333,7 @@ class RelationTest < ActiveRecord::TestCase 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.*').group('id') + dev_with_count = Developer.limit(1) & Developer.order('id DESC') & Developer.select('developers.*') assert_equal [developers(:poor_jamis)], dev_with_count.to_a end -- cgit v1.2.3 From e9e20ab6013424c098c88d357d210068a32a1b39 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 28 Dec 2009 03:19:31 +0530 Subject: Use arel#from instead of the current hack --- activerecord/lib/active_record/relation.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index d0f6c5a63f..a789337027 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -21,7 +21,8 @@ module ActiveRecord offset(r.skipped). select(r.send(:select_clauses).join(', ')). eager_load(r.eager_load_associations). - preload(r.associations_to_preload) + preload(r.associations_to_preload). + from(r.send(:sources).any? ? r.send(:from_clauses) : nil) end alias :& :merge @@ -42,12 +43,8 @@ module ActiveRecord selects.present? ? create_new_relation(@relation.project(selects)) : create_new_relation end - # TODO : This is temporary. We need .from in Arel. - attr_writer :from def from(from) - relation = create_new_relation - relation.from = from - relation + from.present? ? create_new_relation(@relation.from(from)) : create_new_relation end def group(groups) @@ -130,7 +127,7 @@ module ActiveRecord :conditions => where_clause, :limit => @relation.taken, :offset => @relation.skipped, - :from => @from + :from => (@relation.send(:from_clauses) if @relation.send(:sources).any?) }, ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, @eager_load_associations, nil)) end @@ -303,9 +300,7 @@ module ActiveRecord end def create_new_relation(relation = @relation, readonly = @readonly, preload = @associations_to_preload, eager_load = @eager_load_associations) - r = self.class.new(@klass, relation, readonly, preload, eager_load) - r.from = @from - r + self.class.new(@klass, relation, readonly, preload, eager_load) end def where_clause(join_string = "\n\tAND ") -- cgit v1.2.3 From a0ff5f82c37f312a808dbbdb6191fbf20a750775 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Mon, 28 Dec 2009 03:22:33 +0530 Subject: Dont delegate relation#find to to_a --- activerecord/lib/active_record/relation.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index a789337027..530402bf5d 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -1,7 +1,7 @@ module ActiveRecord class Relation delegate :to_sql, :to => :relation - delegate :length, :collect, :find, :map, :each, :to => :to_a + delegate :length, :collect, :map, :each, :to => :to_a attr_reader :relation, :klass, :associations_to_preload, :eager_load_associations def initialize(klass, relation, readonly = false, preload = [], eager_load = []) -- cgit v1.2.3