Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have an app that has a number of Post models, each of which belongs_to a User model. When these posts are published, a PublishedPost model is created that belongs_to the relevant Post model.

I'm trying to build an ActiveRecord query to find published posts that match a user name, then get the ids of those published posts, but I'm getting an error when I try to use the pluck method after eager-loading my associations and searching them with the where method.

Here's (part of) my controller:

class PublishedPostsController < ApplicationController

  def index
    ar_query = PublishedPost.order("published_posts.created_at DESC")

      if params[:searchQuery].present?
        search_query = params[:searchQuery]
        ar_query = ar_query.includes(:post => :user)
                           .where("users.name like ?", "%#{search_query}%")
      end

    @found_ids = ar_query.pluck(:id)

  ...

  end

end

When the pluck method is called, I get this:

ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'users.name' in 'where clause': SELECT id FROM `published_posts`  WHERE (users.name like '%Andrew%') ORDER BY published_posts.created_at DESC

I can get the results I'm looking for with

@found_ids = ar_query.select(:id).map{|r| r.id}

but I'd rather use pluck as it seems like the cleaner way to go. I can't figure out why it's not working, though. Any ideas?

like image 998
amd Avatar asked Jan 22 '13 23:01

amd


2 Answers

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

like image 66
Geoff Avatar answered Oct 16 '22 19:10

Geoff


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")
like image 33
monozok Avatar answered Oct 16 '22 19:10

monozok