ActiveRecord: can't use `pluck` after `where` clause with eager-loaded associations

巧了我就是萌 提交于 2019-12-05 01:29:13

You need to and should do joins instead of includes here.

The two functions are pretty similar except that the data from joins is not returned in the result of the query whereas the data in an includes is.

In that respect, includes and pluck are kind of antithetical. One says to return me all the data you possibly can, whereas the other says to only give me only this one little bit.

Since you only want a small amount of the data, you want to do joins. (Strangely select which also seems somewhat antithetical still works, but you would need to remove the ambiguity over id in this case.)

Try it out in the console and you'll see that includes causes a query that looks kind of like this: SELECT "posts"."id" as t0_ro, "posts"."text" as t0_r1, "users"."id" as t1_r0, "users"."name" as t1_r1 ... When you tack on a pluck statement all those crazy tx_ry columns go away and are replaced by whatever you specified.

I hope that helps, but if not maybe this RailsCast can. It is explained around the 5 minute mark.

http://railscasts.com/episodes/181-include-vs-joins

If you got here by searching "rails pluck ambiguous column", you may want to know you can just replace query.pluck(:id) with:

query.pluck("table_name.id")

Your query wouldn't work as it is written, even without the pluck call.

Reason being, your WHERE clause includes literal SQL referencing the users table which Rails doesn't notice and decides to use multiple queries and join in memory ( .preload() ) instead of joining in the database level ( .eager_load() ):

SELECT * from published_posts WHERE users.name like "pattern" ORDER BY published_posts.created_at DESC
SELECT * from posts WHERE id IN ( a_list_of_all_post_ids_in_publised_posts_returned_above )
SELECT * from users WHERE id IN ( a_list_of_all_user_ids_in_posts_returned_above )

The first of the 3 queries fails and it is the error you get.

To force Rails use a JOIN here, you should either use the explicit .eager_load() instead of .includes(), or add a .references() clause.

Other than that, what @Geoff answered stands, you don't really need to .includes() here, but rather a .joins().

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!