提交 2d6088ce 编写于 作者: P Patrick Rebsch

Retain selections with `includes` and `joins`

Applying `includes` and `joins` to a relation that selected additional
database fields would cause those additional fields not to be included
in the results even though they were queried from the database:

    posts = Post.select('1 as other').includes(:tbl).joins(:tbl)

    posts.to_sql.include?('1 as other')       #=> true
    posts.first.attributes.include?('other')  #=> false

This commit includes these additionally selected fields in the
instantiated results.
上级 05a6cd55
* Retain explicit selections on the base model after applying `includes` and `joins`.
Resolves #34889.
*Patrick Rebsch*
* Allow attributes to be fetched from Arel node groupings.
*Jeff Emminger*, *Gannon McGibbon*
......
......@@ -105,7 +105,9 @@ def instantiate(result_set, &block)
model_cache = Hash.new { |h, klass| h[klass] = {} }
parents = model_cache[join_root]
column_aliases = aliases.column_aliases join_root
column_aliases += explicit_selections(column_aliases, result_set)
message_bus = ActiveSupport::Notifications.instrumenter
......@@ -135,6 +137,13 @@ def apply_column_aliases(relation)
private
attr_reader :alias_tracker
def explicit_selections(root_column_aliases, result_set)
root_names = root_column_aliases.map(&:name).to_set
result_set.columns
.reject { |n| root_names.include?(n) || n =~ /\At\d+_r\d+\z/ }
.map { |n| Aliases::Column.new(n, n) }
end
def aliases
@aliases ||= Aliases.new join_root.each_with_index.map { |join_part, i|
columns = join_part.column_names.each_with_index.map { |column_name, j|
......
......@@ -2,10 +2,11 @@
require "cases/helper"
require "models/post"
require "models/comment"
module ActiveRecord
class SelectTest < ActiveRecord::TestCase
fixtures :posts
fixtures :posts, :comments
def test_select_with_nil_argument
expected = Post.select(:title).to_sql
......@@ -23,5 +24,20 @@ def test_reselect_with_default_scope_select
assert_equal expected, actual
end
def test_aliased_select_using_as_with_joins_and_includes
posts = Post.select("posts.id AS field_alias").joins(:comments).includes(:comments)
assert_includes posts.first.attributes, "field_alias"
end
def test_aliased_select_not_using_as_with_joins_and_includes
posts = Post.select("posts.id field_alias").joins(:comments).includes(:comments)
assert_includes posts.first.attributes, "field_alias"
end
def test_star_select_with_joins_and_includes
posts = Post.select("posts.*").joins(:comments).includes(:comments)
assert_not_includes posts.first.attributes, "posts.*"
end
end
end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册