Domanda

The following are my three models: many users can each have many products (and vice versa) through an associations model.

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

This works great. But now I want to add 2 different association types, a 'strong-association' and 'weak-association' on top of the original association.

What is the best way to go about this?

So far I've considered 1) adding a type column to my association table to specify whether it is a strong/medium/weak association 2) adding a strong-association and also a weak-association record. Both methods seem troublesome when I want to display only a particular association type in my rails view.

I also want to be able to easily change the association type in my project.

È stato utile?

Soluzione

You should definitely add a new field to your associations join table: this is the correct way to store this relationship. There's various things you could do after that.

You could add some new has_many associations:

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

And then do something like (on the page)

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

Or, you could not bother with the new has_many associations, and just split the association records up on the page:

<% 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 %>

Altri suggerimenti

If you want to change the association type I would recommend the extra column for your association table. You can filter out what kinds of records you want to show in your controller action by first gathering up all the associations and then calling a method like #select. For example, to get all the 'weak' associations you could use the following code in your controller action (I'm just using a "show" action for an example. I'm not sure what your situation calls for):

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

You could change what select looks for according to what type of association you want.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top