2012-05-24 37 views
2

是否可以檢查has_many中是否存在多個關聯?在這種情況下,我想檢查是否有一本書有三個標籤「a」,「b」和「c」。Rails:檢查has_many中是否存在關聯

(圖書和標籤通過許多關聯到很多。)

if Book.all.tags.find("a", "b", "c").any? 
    # Yay! 
    # There is at least one book with all three tags (a, b & c) 
end 
+0

非常感謝你。我在這裏找到了一個解決方案:[http://stackoverflow.com/questions/5835696/rails-has-many-through-associations-find-with-and-condition-not-or-conditio][1] [1]:http://stackoverflow.com/questions/5835696/rails-has-many-through-associations-find-with-and-condition-not-or-conditio – Railsana

回答

2

我用這個查詢結構:

Book 
    .select('distinct books.*') 
    .joins(:tags) 
    .where('tags.slug' => ['a', 'b', 'c']) 
    .group("pages.id") 
    .having("count(*) = #{['a', 'b', 'c'].size}") 
3

我認爲這會做的伎倆(適用於has_many):

Book.includes(:tags).where(tags: { name: ['a', 'b', 'c'] }).any? 

其分解:

includes告訴Rails使用急切加載來加載標籤,而不是一次加載一個標籤。這也會導致它在查詢中注意tags並生成更智能的查詢。

where條件非常簡單,並且傳遞數組只是將=比較轉換爲IN ('a', 'b', 'c')條件。

Rails是智能的any?,所以不是加載記錄(它產生一個花哨的查詢,順便說一句)它會生成一個只加載計數。

+1

是不是要返回所有有三個標籤中的任何*的書籍,而不是*全部*? – spike

+0

謝謝你的好方法!正如* spike *所提到的,使用這個查詢**這些標籤中的任何**都是必需的,而不是**全部**。任何想法如何解決這個問題? – Railsana

1

我從來沒有找到一種優雅的導軌方式來解決這個問題,所以希望別人會有更好的答案。

粗魯的方法是下降到SQL。我正在寫這個內存不足,所以可能有語法問題。

在Book模型中就像這樣。這些表的短名稱不會與父查詢衝突。

def self.with_tag(tag) 
    where("EXISTS (SELECT 1 from books_tags bt, tags t where bt.tag_id = t.id 
    and bt.book_id = books.id and t.name = ?)", tag) 
end 

然後,您可以撥打Book.with_tag('a').with_tag('b').with_tag('c')或定義其他方法。不確定是否需要範圍變量。

def self.with_all_tags(tags) 
    scope = self.scoped 
    tags.each do |t| 
     scope = scope.with_tag(t) 
    end 
end 
相關問題