diff options
author | Radoslav Stankov <rstankov@gmail.com> | 2012-04-29 21:17:57 +0300 |
---|---|---|
committer | Radoslav Stankov <rstankov@gmail.com> | 2012-05-17 02:36:13 +0300 |
commit | 64872d1e34d929ee30041b37900591aade2a5eaf (patch) | |
tree | 65288d3fdd80559ecbe655c15b83ce19e49c8906 /activerecord | |
parent | 78b6fdd89f541dfedd369da9957ee6eab9a8a586 (diff) | |
download | rails-64872d1e34d929ee30041b37900591aade2a5eaf.tar.gz rails-64872d1e34d929ee30041b37900591aade2a5eaf.tar.bz2 rails-64872d1e34d929ee30041b37900591aade2a5eaf.zip |
Relation#from to accept other Relation objects
Record.from("(#{sub_query.to_sql})") -> Record.from(sub_query)
Record.from("(#{sub_query.to_sql}) a") -> Record.from(sub_query, :a)
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 7 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/merger.rb | 3 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/query_methods.rb | 34 | ||||
-rw-r--r-- | activerecord/test/cases/relation_test.rb | 7 | ||||
-rw-r--r-- | activerecord/test/cases/relations_test.rb | 7 |
5 files changed, 51 insertions, 7 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index d19e0c9e9b..198b054f99 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,12 @@ ## Rails 4.0.0 (unreleased) ## +* Added ability to ActiveRecord::Relation#from to accept other ActiveRecord::Relation objects + + Record.from(subquery) + Record.from(subquery, :a) + + *Radoslav Stankov* + * Added custom coders support for ActiveRecord::Store. Now you can set your custom coder like this: diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index 3f880ce5e9..36f98c6480 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -43,7 +43,7 @@ module ActiveRecord def normal_values Relation::SINGLE_VALUE_METHODS + Relation::MULTI_VALUE_METHODS - - [:where, :order, :bind, :reverse_order, :lock, :create_with, :reordering] + [:where, :order, :bind, :reverse_order, :lock, :create_with, :reordering, :from] end def merge @@ -76,6 +76,7 @@ module ActiveRecord end def merge_single_values + relation.from_value = values[:from] unless relation.from_value relation.lock_value = values[:lock] unless relation.lock_value relation.reverse_order_value = values[:reverse_order] diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 29536b16c4..19fe8155d9 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -300,12 +300,25 @@ module ActiveRecord self end - def from(value) - spawn.from!(value) + # Specifies table from which the records will be fetched. For example: + # + # Topic.select('title').from('posts') + # #=> SELECT title FROM posts + # + # Can accept other relation objects. For example: + # + # Topic.select('title').from(Topics.approved) + # # => SELECT title FROM (SELECT * FROM topics WHERE approved = 't') subquery + # + # Topics.select('a.title').from(Topics.approved, :a) + # # => SELECT a.title FROM (SELECT * FROM topics WHERE approved = 't') a + # + def from(value, subquery_name = nil) + spawn.from!(value, subquery_name) end - def from!(value) - self.from_value = value + def from!(value, subquery_name = nil) + self.from_value = [value, subquery_name] self end @@ -415,7 +428,7 @@ module ActiveRecord build_select(arel, select_values.uniq) arel.distinct(uniq_value) - arel.from(from_value) if from_value + arel.from(build_from) if from_value arel.lock(lock_value) if lock_value arel @@ -464,6 +477,17 @@ module ActiveRecord end end + def build_from + opts, name = from_value + case opts + when Relation + name ||= 'subquery' + opts.arel.as(name.to_s) + else + opts + end + end + def build_joins(manager, joins) buckets = joins.group_by do |join| case join diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 8a7a2441d4..89f818a689 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -203,13 +203,18 @@ module ActiveRecord assert_equal [], relation.extending_values end - (Relation::SINGLE_VALUE_METHODS - [:lock, :reordering, :reverse_order, :create_with]).each do |method| + (Relation::SINGLE_VALUE_METHODS - [:from, :lock, :reordering, :reverse_order, :create_with]).each do |method| test "##{method}!" do assert relation.public_send("#{method}!", :foo).equal?(relation) assert_equal :foo, relation.public_send("#{method}_value") end end + test '#from!' do + assert relation.from!('foo').equal?(relation) + assert_equal ['foo', nil], relation.from_value + end + test '#lock!' do assert relation.lock!('foo').equal?(relation) assert_equal 'foo', relation.lock_value diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 76b868c7b4..dee31f4772 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -133,6 +133,13 @@ class RelationTest < ActiveRecord::TestCase assert topics.loaded? end + def test_finiding_with_subquery + relation = Topic.where(:approved => true) + assert_equal relation.to_a, Topic.select('*').from(relation).to_a + assert_equal relation.to_a, Topic.select('subquery.*').from(relation).to_a + assert_equal relation.to_a, Topic.select('a.*').from(relation, :a).to_a + end + def test_finding_with_conditions assert_equal ["David"], Author.where(:name => 'David').map(&:name) assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name) |