【问题标题】:Rails associations (many-to-many nightmare)Rails 关联(多对多的噩梦)
【发布时间】:2011-05-15 23:38:34
【问题描述】:

我有一个拥有许多产品的组织。这些产品属于各种类别。还有不止一个组织。而且一个产品可以属于多个类别。

我将如何设置我的模型和关联,以便我可以执行以下操作:

@org = Organisation.first

@org.categories  => spits out a list of categories being used by the products for that organisation
@org.products => spits out a list of products for that organisation
@org.categories[0].products => spits out a list of products for the first category

另外,我希望其他组织可以使用这些类别,这样如果我在组织 1 中添加产品时碰巧创建了一个类别,那么该类别也可用于我为组织 2 添加的产品.

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 database-design activerecord associations


    【解决方案1】:

    这可能是您应该如何设置模型 (docs):

    编辑:更新答案

    class Organisation < ActiveRecord::Base
      has_many :products
    
      def categories
        # I don't like this way anymore
        # @_categories ||= products.map(&:categories).flatten.uniq
        # Do this
        @categories ||= Category.for_organisation(self)
      end
    end
    
    class Product < ActiveRecord::Base
      has_and_belongs_to_many :categories  # foreign keys in the join table
      # A product references an organisation.
      belongs_to :organisation             # foreign key - organisation_id
    end
    
    class Category < ActiveRecord::Base
      has_and_belongs_to_many :products    # foreign keys in the join table
    
      def self.for_organisation(org)
        query = %{
          id in (
            select category_id from categories_products where product_id in (
              select id from products where organisation_id = ? ) )
        }
        where(query, org.id)
      end
    end
    

    可能的陷阱:这需要一个没有对应模型或主键的连接表

    这是一个使用这种技术的example app。自述文件将帮助您入门。

    【讨论】:

    • 我创建了一个规范 gist.github.com/980044 来测试它,并且大部分都可以正常工作!谢谢!但是在第 20 行,它失败并出现错误:Invalid source reflection macro :has_and_belongs_to_many for has_many :categories, :through => :products。使用 :source 指定源反射。
    • @RobZolkos 很高兴我能提供帮助。
    • 我认为事情可能会变得有点不稳定,因为它正在运行 :through 一个 HABTM。可能必须在类别和产品之间明确声明has_many:belongs_to。我会编辑我的答案。可以试试has_many :categories, :through =&gt; :products, :source =&gt; :product,但似乎不太可能。
    • @RobZolkos 我认为:source 可能需要成为连接表的名称。
    • 我认为最好的解决方案可能是组织模型上的自定义类别访问器方法。我已经构建了一个带有扩展测试套件的示例 Rails 应用程序。自述文件将帮助您入门,让我知道您对此解决方案的看法。祝你好运。 github.com/invisiblefunnel/soquestion
    猜你喜欢
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多