12

いくつかのPostモデルがあり、それぞれがモデルでbelongs_toあるアプリがありUserます。これらの投稿が公開されると、関連するモデルのPublishedPostモデルが作成されます。belongs_toPost

ActiveRecordクエリを作成して、ユーザー名に一致する公開された投稿を検索し、それらの公開された投稿のIDを取得しようとしていますがpluck、関連付けを積極的に読み込んで検索した後、このメソッドを使用しようとするとエラーが発生しますメソッドでそれらwhere

これが私のコントローラー(の一部)です:

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

メソッドが呼び出されると、次のpluckようになります。

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

探している結果を得ることができます

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

pluckしかし、私はそれがよりクリーンな方法のように見えるので、むしろ使用したいと思います。しかし、なぜそれが機能しないのか理解できません。何か案は?

4

3 に答える 3

11

joinsここの代わりに行う必要があり、行う必要がありincludesます。

2つの関数は非常に似ていjoinsますが、クエリの結果でからのデータが返されないのに対し、のデータは返されますincludes

その点で、includesそしてpluck一種のアンチテーゼです。1つは、可能な限りすべてのデータを返すように言っていますが、もう1つは、これをほんの少しだけ与えるように言っています。

少量のデータのみが必要なので、実行しますjoins。(不思議なことselectに、これもややアンチテーゼのように見えますがid、この場合はあいまいさを取り除く必要があります。)

コンソールで試してみると、includes次のようなクエリが発生することがわかります。ステートメントを追加SELECT "posts"."id" as t0_ro, "posts"."text" as t0_r1, "users"."id" as t1_r0, "users"."name" as t1_r1 ...するpluckと、これらのクレイジーなtx_ry列がすべてなくなり、指定したものに置き換えられます。

それがお役に立てば幸いですが、そうでない場合は、このRailsCastで可能です。5分前後で説明されています。

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

于 2013-01-23T20:18:20.603 に答える
9

「railspluckambiguouscolumn」を検索してここに到達した場合は、次のように置き換えることができることを知りたいと思うかもしれませんquery.pluck(:id)

query.pluck("table_name.id")
于 2013-12-30T20:44:50.903 に答える
0

pluck呼び出しがなくても、クエリは記述されたとおりに機能しません。

理由は、WHERE句に、Railsが気付かないusersテーブルを参照するリテラルSQLが含まれており、データベースレベル(.eager_load())ではなく、複数のクエリを使用してメモリ(.preload())に結合することを決定した場合です。

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 )

3つのクエリのうち最初のクエリは失敗し、それがエラーになります。

RailsにここでJOINを使用させるには、.includes()の代わりに明示的な.eager_load()を使用するか、.references()句を追加する必要があります。

それ以外は、@ Geoffが答えたのは、ここで.includes()を実行する必要はなく、.joins()を実行する必要があるということです。

于 2014-11-29T22:51:48.370 に答える