2013-01-22 22 views
9

我有一個應用程序,它有多個Post模型,其中每個模型都有belongs_toUser模型。當這些帖子發佈時,PublishedPost模型創建爲belongs_to相關的Post模型。ActiveRecord:不能使用`pluck`在具有熱切加載的關聯的`where'子句之後

我想構建一個ActiveRecord查詢來查找與用戶名匹配的已發佈帖子,然後獲取這些已發佈帖子的ID,但是當我嘗試在eager-加載我的關聯並用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,因爲它似乎更清潔的方式去。但我無法弄清楚它爲什麼不起作用。有任何想法嗎?

回答

10

您需要和應該做joins而不是includes在這裏。

這兩個函數非常相似,只是joins的數據沒有在查詢結果中返回,而includes中的數據是。

在這方面,includespluck是一種對立的。一個人說要把所有可能的數據都還給我,而另一個人說只給我一點點。

既然你只想要少量的數據,你想要做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

9

如果您來到這裏尋找「軌道採摘不明確的列」,你可能想知道你可以將其替換query.pluck(:id)

query.pluck("table_name.id") 
+0

Yessss!我不知道爲什麼這不是在文檔中?至少我沒有看到它。 – FireDragon

0

您的查詢是行不通的,因爲它是寫下來,即使沒有撥打電話。

原因是,您的WHERE子句包括引用用戶表的文字SQL,Rails沒有注意到並決定使用多個查詢並加入內存(.preload())而不是加入數據庫級別(。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) 

3個查詢中的第1個失敗,這是您得到的錯誤。

要強制Rails在這裏使用JOIN,您應該使用明確的.eager_load()而不是.includes(),或者添加.references()子句。

除此之外,@Geoff回答的是什麼,您並不需要.includes()在這裏,而是.joins()。

相關問題