【问题标题】:Rails: Check if associations exist in has_manyRails:检查has_many中是否存在关联
【发布时间】:2012-05-30 13:43:34
【问题描述】:

是否可以检查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

【问题讨论】:

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


【解决方案1】:

我使用这个查询结构:

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

【讨论】:

    【解决方案2】:

    我从未找到解决此问题的优雅 Rails 方法,因此希望其他人能提供更好的答案。

    野蛮的方法是下拉到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
    

    【讨论】:

      【解决方案3】:

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

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

      分解:

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

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

      Rails 对 any? 很聪明,因此它不会加载记录(这会生成一个花哨的查询,顺便说一句),它会生成一个只加载计数的记录。

      【讨论】:

      • 这不是要返回所有具有 any 三个标签的书,而不是 all
      • 感谢您的好方法!正如 spike 所提到的,对于这个查询,any 这些标签是必需的,而不是 all。任何想法如何解决这个问题?
      猜你喜欢
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 2017-12-10
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多