diff options
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/querying.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/query_methods.rb | 20 | ||||
-rw-r--r-- | activerecord/test/cases/relation_test.rb | 15 |
4 files changed, 35 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/querying.rb b/activerecord/lib/active_record/querying.rb index 09da9ad1d1..94e34e1bd4 100644 --- a/activerecord/lib/active_record/querying.rb +++ b/activerecord/lib/active_record/querying.rb @@ -8,7 +8,7 @@ module ActiveRecord delegate :find_each, :find_in_batches, :to => :scoped delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, - :having, :create_with, :uniq, :to => :scoped + :having, :create_with, :uniq, :references, :to => :scoped delegate :count, :average, :minimum, :maximum, :sum, :calculate, :pluck, :to => :scoped # Executes a custom SQL query against your database and returns all the results. The results will diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 3d6478c918..0f8ac33f6e 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -6,7 +6,7 @@ module ActiveRecord class Relation JoinOperation = Struct.new(:relation, :join_class, :on) ASSOCIATION_METHODS = [:includes, :eager_load, :preload] - MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind] + MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind, :references] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reordering, :reverse_order, :uniq] include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches, Explain, Delegation diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 44ff8f7b22..7b340c1b64 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -10,7 +10,7 @@ module ActiveRecord :where_values, :having_values, :bind_values, :limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value, :from_value, :reordering_value, :reverse_order_value, - :uniq_value + :uniq_value, :references_values def includes(*args) args.reject! {|a| a.blank? } @@ -38,6 +38,24 @@ module ActiveRecord relation end + # Used to indicate that an association is referenced by an SQL string, and should + # therefore be JOINed in any query rather than loaded separately. + # + # For example: + # + # User.includes(:posts).where("posts.name = 'foo'") + # # => Doesn't JOIN the posts table, resulting in an error. + # + # User.includes(:posts).where("posts.name = 'foo'").references(:posts) + # # => Query now knows the string references posts, so adds a JOIN + def references(*args) + return self if args.blank? + + relation = clone + relation.references_values = (references_values + args).uniq + relation + end + # Works in two unique ways. # # First: takes a block so it can be used just like Array#select. diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 7a75a8436b..5a6a3b81de 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -44,7 +44,7 @@ module ActiveRecord end def test_multi_value_methods - assert_equal [:select, :group, :order, :joins, :where, :having, :bind].map(&:to_s).sort, + assert_equal [:select, :group, :order, :joins, :where, :having, :bind, :references].map(&:to_s).sort, Relation::MULTI_VALUE_METHODS.map(&:to_s).sort end @@ -135,5 +135,18 @@ module ActiveRecord relation.eager_load_values << :b assert relation.eager_loading? end + + def test_references_values + relation = Relation.new :a, :b + assert_equal [], relation.references_values + relation = relation.references(:foo).references(:omg, :lol) + assert_equal [:foo, :omg, :lol], relation.references_values + end + + def test_references_values_dont_duplicate + relation = Relation.new :a, :b + relation = relation.references(:foo).references(:foo) + assert_equal [:foo], relation.references_values + end end end |