【问题标题】:Multiple association types between 2 models2个模型之间的多种关联类型
【发布时间】:2014-03-18 16:25:05
【问题描述】:

以下是我的三个模型:许多用户可以通过关联模型拥有许多产品(反之亦然)。

class Product < ActiveRecord::Base
  has_many :associations
  has_many :users, :through => :associations
end

class User < ActiveRecord::Base
  has_many :associations
  has_many :products, :through => :associations
end

class Association < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
end

这很好用。但现在我想在原始关联之上添加 2 种不同的关联类型,“强关联”和“弱关联”。

解决此问题的最佳方法是什么?

到目前为止,我已经考虑过 1) 在关联表中添加一个类型列以指定它是强/中/弱关联 2) 添加强关联和弱关联记录。当我只想在 Rails 视图中显示特定的关联类型时,这两种方法似乎都很麻烦。

我还希望能够在我的项目中轻松更改关联类型。

【问题讨论】:

    标签: ruby-on-rails ruby model model-associations


    【解决方案1】:

    您绝对应该在您的关联连接表中添加一个新字段:这是存储此关系的正确方法。在那之后你可以做很多事情。

    您可以添加一些新的 has_many 关联:

    class Product < ActiveRecord::Base
      has_many :associations
      has_many :users, :through => :associations
      has_many :weak_associated_users, :class_name => "User", :through => :associations, :source => :user, :conditions => ["associations.strength = ?", "weak"]
      has_many :medium_associated_users, :class_name => "User", :through => :associations, :source => :user, :conditions => ["associations.strength = ?", "medium"]
      has_many :strong_associated_users, :class_name => "User", :through => :associations, :source => :user, :conditions => ["associations.strength = ?", "strong"]
    end
    
    class User < ActiveRecord::Base
      has_many :associations
      has_many :products, :through => :associations
      has_many :weak_associated_products, :class_name => "Product", :through => :associations, :source => :product, :conditions => ["associations.strength = ?", "weak"]
      has_many :medium_associated_products, :class_name => "Product", :through => :associations, :source => :product, :conditions => ["associations.strength = ?", "medium"]
      has_many :strong_associated_products, :class_name => "Product", :through => :associations, :source => :product, :conditions => ["associations.strength = ?", "strong"]     
    end
    
    #fields: user_id, product_id, strength
    class Association < ActiveRecord::Base
      belongs_to :user
      belongs_to :product
    end
    

    然后做类似(在页面上)的事情

    <h2>Strongly association users</h2>
    <% @product.strong_associated_users.each do |user| %>
      ...show user info here
    <% end %>
    

    或者,您可以不理会新的 has_many 关联,只需在页面上拆分关联记录:

    <% grouped = @product.associations.find(:all, :include => [:user]).group_by(&:strength) %>
    <% ["weak", "medium", "strong"].each do |strength| %>
      <% if associations = grouped[strength] %>
        <h2><%= strength %> associations</h2>#
        <% associations.each do |association| %>
          <% user = association.user %>
          ...show user info here
        <% end %>
      <% end %>
    <% end %>
    

    【讨论】:

    • 我收到“ActiveRecord::HasManyThroughSourceAssociationNotFoundError”
    • 在模型关联中找不到源关联 :weak_associated_product 或 :weak_associated_products。
    • 我的错误 - 对不起。我忘记了您需要使用:source 选项告诉Rails 从连接表类中使用哪个关联。通常,当关联名称与表名称匹配时,它会自行解决。我已经编辑了我的答案。
    • 我通常调用 user.products
    • 您需要创建一个连接类的实例。例如user.associations.create(:product =&gt; @product, :strength =&gt; "medium")
    【解决方案2】:

    如果您想更改关联类型,我建议您为关联表添加额外的列。您可以通过首先收集所有关联然后调用 #select 之类的方法来过滤出要在控制器操作中显示的记录类型。例如,要获得所有“弱”关联,您可以在控制器操作中使用以下代码(我只是使用“显示”操作作为示例。我不确定您的情况需要什么):

    def show
      @products = current_user.products.select! { |p| p.association_type == "weak" } 
      #associations scoped through current_user
      #also, asociation_type is just a placeholder name for whatever you name that extra column
    
      render :show #@products are all products with "weak" association
    end
    

    您可以根据您想要的关联类型更改 select 查找的内容。

    【讨论】:

    • 似乎不起作用,@products 没有被关联类型过滤
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多