aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/lib/active_record/querying.rb2
-rw-r--r--activerecord/lib/active_record/relation.rb2
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb20
-rw-r--r--activerecord/test/cases/relation_test.rb15
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