mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Allow ActiveRecord::Relation merges to maintain context of joined associations
This commit is contained in:
parent
5f62c86b50
commit
0d8cf53296
4 changed files with 43 additions and 6 deletions
|
@ -109,7 +109,7 @@ module ActiveRecord
|
||||||
case associations
|
case associations
|
||||||
when Symbol, String
|
when Symbol, String
|
||||||
reflection = parent.reflections[associations.to_s.intern] or
|
reflection = parent.reflections[associations.to_s.intern] or
|
||||||
raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?"
|
raise ConfigurationError, "Association named '#{ associations }' was not found on #{parent.active_record.name}; perhaps you misspelled it?"
|
||||||
unless join_association = find_join_association(reflection, parent)
|
unless join_association = find_join_association(reflection, parent)
|
||||||
@reflections << reflection
|
@reflections << reflection
|
||||||
join_association = build_join_association(reflection, parent)
|
join_association = build_join_association(reflection, parent)
|
||||||
|
|
|
@ -55,7 +55,12 @@ module ActiveRecord
|
||||||
|
|
||||||
def find_parent_in(other_join_dependency)
|
def find_parent_in(other_join_dependency)
|
||||||
other_join_dependency.join_parts.detect do |join_part|
|
other_join_dependency.join_parts.detect do |join_part|
|
||||||
parent == join_part
|
case parent
|
||||||
|
when JoinBase
|
||||||
|
parent.active_record == join_part.active_record
|
||||||
|
else
|
||||||
|
parent == join_part
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
class Merger
|
class Merger
|
||||||
attr_reader :relation, :values
|
attr_reader :relation, :other
|
||||||
|
|
||||||
def initialize(relation, other)
|
def initialize(relation, other)
|
||||||
if other.default_scoped? && other.klass != relation.klass
|
if other.default_scoped? && other.klass != relation.klass
|
||||||
|
@ -37,13 +37,17 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
@relation = relation
|
@relation = relation
|
||||||
@values = other.values
|
@other = other
|
||||||
|
end
|
||||||
|
|
||||||
|
def values
|
||||||
|
@other.values
|
||||||
end
|
end
|
||||||
|
|
||||||
def normal_values
|
def normal_values
|
||||||
Relation::SINGLE_VALUE_METHODS +
|
Relation::SINGLE_VALUE_METHODS +
|
||||||
Relation::MULTI_VALUE_METHODS -
|
Relation::MULTI_VALUE_METHODS -
|
||||||
[:where, :order, :bind, :reverse_order, :lock, :create_with, :reordering]
|
[:where, :joins, :order, :bind, :reverse_order, :lock, :create_with, :reordering]
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge
|
def merge
|
||||||
|
@ -54,6 +58,7 @@ module ActiveRecord
|
||||||
|
|
||||||
merge_multi_values
|
merge_multi_values
|
||||||
merge_single_values
|
merge_single_values
|
||||||
|
merge_joins
|
||||||
|
|
||||||
relation
|
relation
|
||||||
end
|
end
|
||||||
|
@ -84,6 +89,26 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def merge_joins
|
||||||
|
return if values[:joins].blank?
|
||||||
|
|
||||||
|
if other.klass == relation.klass
|
||||||
|
relation.joins!(values[:joins])
|
||||||
|
else
|
||||||
|
joins_to_stash, other_joins = values[:joins].partition { |join|
|
||||||
|
case join
|
||||||
|
when Hash, Symbol, Array
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
join_dependency = ActiveRecord::Associations::JoinDependency.new(other.klass, joins_to_stash, [])
|
||||||
|
relation.joins!(join_dependency.join_associations + other_joins)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def merged_binds
|
def merged_binds
|
||||||
if values[:bind]
|
if values[:bind]
|
||||||
(relation.bind_values + values[:bind]).uniq(&:first)
|
(relation.bind_values + values[:bind]).uniq(&:first)
|
||||||
|
|
|
@ -6,6 +6,7 @@ require 'models/topic'
|
||||||
require 'models/comment'
|
require 'models/comment'
|
||||||
require 'models/author'
|
require 'models/author'
|
||||||
require 'models/comment'
|
require 'models/comment'
|
||||||
|
require 'models/rating'
|
||||||
require 'models/entrant'
|
require 'models/entrant'
|
||||||
require 'models/developer'
|
require 'models/developer'
|
||||||
require 'models/reply'
|
require 'models/reply'
|
||||||
|
@ -19,7 +20,7 @@ require 'models/minivan'
|
||||||
|
|
||||||
class RelationTest < ActiveRecord::TestCase
|
class RelationTest < ActiveRecord::TestCase
|
||||||
fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
|
fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments,
|
||||||
:tags, :taggings, :cars, :minivans
|
:ratings, :tags, :taggings, :cars, :minivans
|
||||||
|
|
||||||
def test_do_not_double_quote_string_id
|
def test_do_not_double_quote_string_id
|
||||||
van = Minivan.last
|
van = Minivan.last
|
||||||
|
@ -731,6 +732,12 @@ class RelationTest < ActiveRecord::TestCase
|
||||||
assert_equal 1, comments.count
|
assert_equal 1, comments.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_relation_merging_with_merged_joins
|
||||||
|
special_comments_with_ratings = SpecialComment.joins(:ratings)
|
||||||
|
posts_with_special_comments_with_ratings = Post.group("posts.id").joins(:special_comments).merge(special_comments_with_ratings)
|
||||||
|
assert_equal 1, authors(:david).posts.merge(posts_with_special_comments_with_ratings).to_a.length
|
||||||
|
end
|
||||||
|
|
||||||
def test_count
|
def test_count
|
||||||
posts = Post.scoped
|
posts = Post.scoped
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue