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
|
||||
when Symbol, String
|
||||
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)
|
||||
@reflections << reflection
|
||||
join_association = build_join_association(reflection, parent)
|
||||
|
|
|
@ -55,7 +55,12 @@ module ActiveRecord
|
|||
|
||||
def find_parent_in(other_join_dependency)
|
||||
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
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
class Merger
|
||||
attr_reader :relation, :values
|
||||
attr_reader :relation, :other
|
||||
|
||||
def initialize(relation, other)
|
||||
if other.default_scoped? && other.klass != relation.klass
|
||||
|
@ -37,13 +37,17 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
@relation = relation
|
||||
@values = other.values
|
||||
@other = other
|
||||
end
|
||||
|
||||
def values
|
||||
@other.values
|
||||
end
|
||||
|
||||
def normal_values
|
||||
Relation::SINGLE_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
|
||||
|
||||
def merge
|
||||
|
@ -54,6 +58,7 @@ module ActiveRecord
|
|||
|
||||
merge_multi_values
|
||||
merge_single_values
|
||||
merge_joins
|
||||
|
||||
relation
|
||||
end
|
||||
|
@ -84,6 +89,26 @@ module ActiveRecord
|
|||
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
|
||||
if values[:bind]
|
||||
(relation.bind_values + values[:bind]).uniq(&:first)
|
||||
|
|
|
@ -6,6 +6,7 @@ require 'models/topic'
|
|||
require 'models/comment'
|
||||
require 'models/author'
|
||||
require 'models/comment'
|
||||
require 'models/rating'
|
||||
require 'models/entrant'
|
||||
require 'models/developer'
|
||||
require 'models/reply'
|
||||
|
@ -19,7 +20,7 @@ require 'models/minivan'
|
|||
|
||||
class RelationTest < ActiveRecord::TestCase
|
||||
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
|
||||
van = Minivan.last
|
||||
|
@ -731,6 +732,12 @@ class RelationTest < ActiveRecord::TestCase
|
|||
assert_equal 1, comments.count
|
||||
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
|
||||
posts = Post.scoped
|
||||
|
||||
|
|
Loading…
Reference in a new issue