I've added a link in the pull request you mention so that people finding 
this in Github's issues view can track this.

El sábado, 20 de abril de 2019, 7:27:55 (UTC+2), Stan Lo escribió:
>
> From the examples in documents, it looks like AR#pluck is mainly for 
> retrieving columns from the same table. Like 
> Post.pluck(:author_id)
>
> But we can also find some people using pluck for joined tables' columns, 
> like 
> Post.joins(:author).pluck("author.name", :title)
>
> And normally this works fine, except for cases like 
> https://github.com/rails/rails/issues/36042. 
>
> class Post < ActiveRecord::Base
>   enum status: {
>     a: "a",
>     b: "b",
>     c: "c"
>   }
>   has_many :comments
> end
>
> class Comment < ActiveRecord::Base
>   enum status: {
>     red: "red",
>     green: "green",
>     blue: "blue"
>   }
>   belongs_to :post
> end
>
> class BugTest < Minitest::Test
>   def test_association_stuff
>     post = Post.create!(status: "a")
>     post.comments << Comment.create!(status: "blue", not_enum: "blue")
>
>     expected = [["a", "blue", "blue"]]
>     actual = Post.includes(:comments).pluck(:status, "comments.status", 
> "comments.not_enum")
>     assert_equal expected, actual
>   end
> end
>
>
> After digging into the issue, I think plucking joined tables' columns is 
> kind of a misuse of pluck. Here's the source code of pluck
>
>     def pluck(*column_names)
>       if loaded? && (column_names.map(&:to_s) - @klass.attribute_names - 
> @klass.attribute_aliases.keys).empty?
>         return records.pluck(*column_names)
>       end
>
>       if has_include?(column_names.first)
>         relation = apply_join_dependency
>         relation.pluck(*column_names)
>       else
>         klass.disallow_raw_sql!(column_names)
>         relation = spawn
>         relation.select_values = column_names
>         result = skip_query_cache_if_necessary { 
> klass.connection.select_all(relation.arel, nil) }
>         result.cast_values(klass.attribute_types)
>       end
>     end
>
>
> And the cause of the issue above is 
>
> result.cast_values(klass.attribute_types)
>
> Pluck seems assume it'll only be used for the same table, so it uses the 
> original class' attribute types to cast column values (in this case, the 
> Post's attribute types). Hence when the joined table's columns need 
> different casting methods (like different enum definitions), Rails may get 
> confused. (For generic types like integer, string that won't be a problem 
> though, that's why most people don't have issue). And for our issue 
> example, Rails tried to use Post's status type definition to cast Comment's 
> status type, and as expected it failed.
>
> So my question is, should we have a full support on this behavior? Which 
> means we'd need to be able to cast types for every tables envolved. And 
> this won't be a small change since we now need to get all tables' type 
> definitions. Or we should consider this as a misuse and not receommending 
> using it (or even deprecate it).
>
>
>
>
>
>
>

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rubyonrails-core+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at https://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.

Reply via email to