mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Properly append preload / includes args on Merger
Couldn't find other way to get the association name from a given class other than looping through `reflect_on_all_associations` reflections .. Noticed this one while looking at this example: ```ruby class Product < ActiveRecord::Base has_many :variants has_many :translations end class Translation < ActiveRecord::Base belongs_to :product end class Variant < ActiveRecord::Base belongs_to :product end class BugTest < Minitest::Test def test_merge_stuff product = Product.create! name: 'huhu' variant = Variant.create! product_id: product.id Translation.create! locale: 'en', product_id: product.id product_relation = Product.all .preload(:translations) .joins(:translations) .merge(Translation.where(locale: 'en')) .where(name: 'huhu') assert_equal variant, Variant.joins(:product).merge(product_relation).first end end ```
This commit is contained in:
parent
d0a370ec93
commit
a01d164b94
2 changed files with 50 additions and 2 deletions
|
@ -50,7 +50,7 @@ module ActiveRecord
|
||||||
|
|
||||||
NORMAL_VALUES = Relation::VALUE_METHODS -
|
NORMAL_VALUES = Relation::VALUE_METHODS -
|
||||||
Relation::CLAUSE_METHODS -
|
Relation::CLAUSE_METHODS -
|
||||||
[:joins, :order, :reverse_order, :lock, :create_with, :reordering] # :nodoc:
|
[:includes, :preload, :joins, :order, :reverse_order, :lock, :create_with, :reordering] # :nodoc:
|
||||||
|
|
||||||
def normal_values
|
def normal_values
|
||||||
NORMAL_VALUES
|
NORMAL_VALUES
|
||||||
|
@ -75,6 +75,7 @@ module ActiveRecord
|
||||||
merge_multi_values
|
merge_multi_values
|
||||||
merge_single_values
|
merge_single_values
|
||||||
merge_clauses
|
merge_clauses
|
||||||
|
merge_preloads
|
||||||
merge_joins
|
merge_joins
|
||||||
|
|
||||||
relation
|
relation
|
||||||
|
@ -82,6 +83,27 @@ module ActiveRecord
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def merge_preloads
|
||||||
|
return if other.preload_values.empty? && other.includes_values.empty?
|
||||||
|
|
||||||
|
if other.klass == relation.klass
|
||||||
|
relation.preload! other.preload_values unless other.preload_values.empty?
|
||||||
|
relation.includes! other.includes_values unless other.includes_values.empty?
|
||||||
|
else
|
||||||
|
reflection = relation.klass.reflect_on_all_associations.find do |reflection|
|
||||||
|
reflection.class_name == other.klass.name
|
||||||
|
end || return
|
||||||
|
|
||||||
|
unless other.preload_values.empty?
|
||||||
|
relation.preload! reflection.name => other.preload_values
|
||||||
|
end
|
||||||
|
|
||||||
|
unless other.includes_values.empty?
|
||||||
|
relation.includes! reflection.name => other.includes_values
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def merge_joins
|
def merge_joins
|
||||||
return if other.joins_values.blank?
|
return if other.joins_values.blank?
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ require 'models/tyre'
|
||||||
require 'models/minivan'
|
require 'models/minivan'
|
||||||
require 'models/aircraft'
|
require 'models/aircraft'
|
||||||
require "models/possession"
|
require "models/possession"
|
||||||
|
require "models/reader"
|
||||||
|
|
||||||
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,
|
||||||
|
@ -621,6 +621,32 @@ class RelationTest < ActiveRecord::TestCase
|
||||||
assert_equal 1, query.to_a.size
|
assert_equal 1, query.to_a.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_preloading_with_associations_and_merges
|
||||||
|
post = Post.create! title: 'Uhuu', body: 'body'
|
||||||
|
reader = Reader.create! post_id: post.id, person_id: 1
|
||||||
|
comment = Comment.create! post_id: post.id, body: 'body'
|
||||||
|
|
||||||
|
assert !comment.respond_to?(:readers)
|
||||||
|
|
||||||
|
post_rel = Post.preload(:readers).joins(:readers).where(title: 'Uhuu')
|
||||||
|
result_comment = Comment.joins(:post).merge(post_rel).to_a.first
|
||||||
|
assert_equal comment, result_comment
|
||||||
|
|
||||||
|
assert_no_queries do
|
||||||
|
assert_equal post, result_comment.post
|
||||||
|
assert_equal [reader], result_comment.post.readers.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
post_rel = Post.includes(:readers).where(title: 'Uhuu')
|
||||||
|
result_comment = Comment.joins(:post).merge(post_rel).first
|
||||||
|
assert_equal comment, result_comment
|
||||||
|
|
||||||
|
assert_no_queries do
|
||||||
|
assert_equal post, result_comment.post
|
||||||
|
assert_equal [reader], result_comment.post.readers.to_a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_loading_with_one_association
|
def test_loading_with_one_association
|
||||||
posts = Post.preload(:comments)
|
posts = Post.preload(:comments)
|
||||||
post = posts.find { |p| p.id == 1 }
|
post = posts.find { |p| p.id == 1 }
|
||||||
|
|
Loading…
Reference in a new issue