开发者

Update Mapping Table Attribute in Many to Many Association

开发者 https://www.devze.com 2023-02-25 03:22 出处:网络
I have a many to many association setup in Rails with ActiveRecord. Let\'s say the tables are +------------++----------------++----------+

I have a many to many association setup in Rails with ActiveRecord. Let's say the tables are

+------------+                +----------------+                +----------+
| categories | -- has many -= | category_items | =- has many -- | products | 
+------------+                +----------------+                +----------+

In the category_items table I have the standard set of id's plus an extra attribute called "type":

id:int 
category_id:int
product_id:int
category_type:string

Thankfully, Rails provides some great helpers for making assignment in the mapping table a breeze. For example:

p = Product.first   # p.id => 1
c开发者_开发知识库 = Category.first  # c.id => 1

# now to make the assignment

p.categories << c
# or
p.categories.create(c)

That's all well and good, but let's say I want to automatically update the "type" field with the class name of the other table. So for the examples given above, my category_items row would look like this:

id = 1 (or some number)
category_id = 1 
product_id = 1
category_type = nil

But I would like category_type to equal "Product". Is there a way for me to build a callback or define something in the association that would automatically set the category_type field? I know in polymorphic associations, you can use something like :source or :as to do something like this, but polymorphic associations in many to many associations throws an error.

Any ideas?

Thanks!


Have you tried a polymorphic on category_items like this:

class CategoryItem < ActiveRecord::Base
  belongs_to :category, :polymorphic => true
  belongs_to :product
end

class ACategory < ActiveRecord::Base
  has_many :category_items, :as => :category
end

class AnotherCategory < ActiveRecord::Base
  has_many :category_items, :as => :category
end

class Product < ActiveRecord::Base
  has_many :category_items
end

I think this will do the trick!


I ended up making separate getter/setter methods. In your case, methods on Product:

setter

def set_category_type(category_id, type) 
  category_items = self.category_items.select { |category_item| category_item.category_id == category_id}
  if category_items.length > 0
    category_item = category_items.first
    category_item.type = type
    category_item.save
  else
    CategoryItem.create(:product_id => self.id, :category_id => category_id, :type => type)
  end
end

getter

def category_type(category_id)
  category_item = self.category_items.where(:category_id => category_id ).first()
  if category_item.nil?
    nil # or some other default type value
  else
    category_item.type
  end
end

This was basically what I needed but couldn't find a more elegant way. Please show me a better way if you know.

0

精彩评论

暂无评论...
验证码 换一张
取 消