Rails:检查has_many中是否存在关联

时间:2012-05-24 00:17:02

标签: ruby-on-rails conditional-statements has-many

是否可以检查has_many中是否存在多个关联?在这种情况下,我想检查是否有一本书有三个标签" a"," b"和" c"。

(书籍和标签通过多对多关联。)

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

3 个答案:

答案 0 :(得分:3)

我认为这会解决问题(适用于has_many):

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

打破它:

includes告诉Rails使用预先加载来加载标记,而不是一次加载一个。这也使它在查询中关注tags并生成更智能的查询。

where条件非常简单,传递数组只会将=比较转换为IN ('a', 'b', 'c')条件。

Rails对any?很聪明,所以不是加载记录(生成一个花哨的查询,顺便说一下),而是生成一个只加载计数的记录。

答案 1 :(得分:2)

我使用这个查询结构:

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

答案 2 :(得分: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