Ruby on rails Rails关联(多对多)

Ruby on rails Rails关联(多对多),ruby-on-rails,ruby-on-rails-3,database-design,activerecord,associations,Ruby On Rails,Ruby On Rails 3,Database Design,Activerecord,Associations,我有一个拥有许多产品的组织。这些产品种类繁多。还有不止一个组织。一个产品可以属于多个类别 如何设置模型和关联,以便执行以下操作: @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 th

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

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

@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添加的产品使用。

这可能是您应该设置模型的方式:

编辑:更新答案

可能的问题:这需要一个没有相应模型或主键的联接表


下面是一个使用此技术的示例。自述文件将帮助您开始。

我创建了一个规范来测试这一点,并且大部分都在运行!非常感谢。但是,在第20行,它失败了,错误为:无效的源反射宏:has\u和\u属于\u many for has\u many:categories,:至=>:products。Use:source指定源反射。@RobZolkos很高兴我能帮上忙。我想事情可能会有点不稳定,因为它正在通过HABTM。可能必须在类别和产品之间明确声明has_many's和:behing_to's。我将编辑我的答案。可能尝试使用多个:categories,:through=>:products,:source=>:product,但似乎不太可能奏效。@RobZolkos我认为:source可能需要是联接表的名称。我认为最好的解决方案可能是在组织模型上使用自定义类别访问器方法。我已经用扩展的测试套件构建了一个示例rails应用程序。自述会让你开始,让我知道你对这个解决方案的看法。祝你好运
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