【问题标题】:Get has_many from ActiveRecord::Relaiton从 ActiveRecord::Relation 中获取 has_many
【发布时间】:2015-06-10 16:18:52
【问题描述】:

是否可以从 ActiveRecord::Relation 中获取 has_many 记录?

Book.where(fiction: true).pages 而不是 Book.where(fiction: true).collect { |book| book.pages }

理想情况下,我希望能够使用一个 ActiveRecord 查询来获取所有记录,因此我不必在内存中构建数组,并使代码更简洁,尤其是当关系具有多个级别时(即Book.where(fiction: true).pages.words

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 activerecord rails-activerecord


    【解决方案1】:

    下面,

    Book.where(fiction: true).collect { |book| book.pages }
    

    可以写成:

    Page.joins(:book).where("books.fiction = ?", true)
    

    类似的方式:

    Word.joins(page: :book).where("books.fiction = ?", true)
    

    【讨论】:

    • 如果我已经将初始集合作为关系(例如在视图中),有没有办法做到这一点?即我有@books 并想获得这些书的所有文字。
    • @Asherlc 是的。使用#includes 方法,如Book.includes(:pages).where(fiction: true).. 这是一个单一的查询,它解决了N + 1 问题。
    • @Asherlc 阅读 guides.rubyonrails.org/…
    • 抱歉,我认为我没有很好地解释我的问题。假设我只有一个包含 ActiveRecord::Relation 的变量,并且无法访问原始查询参数。所以我想取一个@books 的实例变量并找到所有相关的页面/单词,只给预建的ActiveRecord::Relation。这可能吗?
    【解决方案2】:

    您可以使用选项through 在父对象(假设它是Library)和pages 之间创建单独的has_many 关系。

    class Page
      belongs_to :book
    end
    
    class Book
      belongs_to :library
      has_many :pages
    end
    
    class Library
      has_many :books
      has_many :pages, through: :books
      has_many :fiction_books, -> { where(fiction: true) }, class_name: 'Book', foreign_key: 'library_id'
      has_many :fiction_pages, through: :fiction_books, source: :pages
    end
    
    Library.first.fiction_pages
    

    我会注意到父对象将帮助您构建具有过于复杂逻辑的正确架构,因此您只需编写 Book.where(fiction: true).pages 而不是 current_library.fiction_pages

    如果应用程序的逻辑不需要这样的父对象,你可以通过单独的助手来伪造它,可以放在ApplicationController

    class ApplicationController
      helper_method :current_library
    
      protected
    
      def current_library
        @current_library ||= Library.first
      end
    
    end
    

    在这种情况下,所有 AR 对象都应该通过 library 方法或通过 library 的 child 获取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      相关资源
      最近更新 更多