【问题标题】:Advanced associations in railsRails 中的高级关联
【发布时间】:2010-01-02 10:54:03
【问题描述】:

现在我正在为我的两个模型使用 has_and_belongs_to_many 关联,如下所示:

class Books < ActiveRecord::Base
    has_and_belongs_to_many :publishers
end

class Publisher < ActiveRecord::Base
    belongs_to :publishing_company
    has_and_belongs_to_many :books
end

您会注意到每个出版商都属于一家出版公司:

class PublishingCompany < ActiveRecord::Base
    has_many :publishers
end

我的目标是建立一个允许我这样做的协会:

PublishingCompany.find(1).books

这对于传统的 RoR 关联是否可行?

【问题讨论】:

    标签: ruby-on-rails associations


    【解决方案1】:

    您正在寻找的概念是在 PublishingCompany 类的 has_many 关联上使用 :through 参数指定二级关联。进行二级关联(将加入 2 个额外的表格)非常常见,但我认为我从未进行过三级关联(出版商 -> 出版商书籍 -> 书籍),如果我记得正确的话,Rails 变得相当草率了解您将关联推到这么远后要尝试做什么。

    第一个值得尝试的选项是:

    class PublishingCompany
      has_many :publishers
      has_many :books, :through => :publishers
    end
    

    但是Rails documentation 声明 :through 参数只能用于 has_many 或 belongs_to,这意味着这不应该通过您拥有的 has_and_belongs_to_many 关联起作用。

    您的第二个选项是我在 Rails 1 上编写的早期系统上必须做的事情。我可能会因此而被否决,但这是我必须做的事情,因为我无法处理 Rails它。

    由于您只会以只读方式使用关联,因此我创建了一个伪造的方法来处理它。请注意,这是最后的手段。作为旁注,我个人不喜欢 has_and_belongs_to_many 关联,因为我觉得奇怪的是,您没有可以操作的对象来表示连接表的行。

    class Books
      has_many :book_publishers
      has_many :publishers, :through => :book_publishers
    end
    
    class BookPublisher
      belongs_to :book
      belongs_to :publisher
    end
    
    class Publisher
      has_many :book_publishers  
      has_many :books, :through => :book_publishers
      belongs_to :publishing_company
    end
    
    class PublishingCompany
      has_many :publishers
      has_many :book_publishers, :through => :publishers
    
      def books
        book_publishers.map{|bp|bp.book}
      end
    end
    
    # typical use, eager loading to avoid N+1
    company = PublishingCompany.first :include => {:book_publishers => :book}
    company.books.each {|b| puts b.title}
    

    【讨论】:

      【解决方案2】:

      这应该适合你。

      class PublishingCompany < ActiveRecord::Base
        has_many :books, :through => :publishers, :source => :books
      end
      

      :source参数是你需要用到的那个

      【讨论】:

        猜你喜欢
        • 2023-03-10
        • 2010-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多