Mapping table attribute update in many associations

I have many different association settings in Rails with ActiveRecord. Let's say tables

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

In the category_items table, I have a standard id set plus an additional attribute called "type":

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

Fortunately, Rails provides great helpers for creating bindings in the mapping table. For instance:

 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) 

This is all good and good, but let me say that I want to automatically update the type field with the class name of another table. Therefore, for the above examples, the category_items line 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 automatically set the category_type field? I know that in polymorphic associations you can use something like: source or: to do something similar, but polymorphic associations in many, many associations cause an error.

Any ideas?

Thanks!

+4
source share
2 answers

Have you tried the polymorphic category_items functions as follows:

 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!

+1
source

As a result, I created separate getter / setter methods. In your case, product methods:

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 could not find a more elegant way. Please show me the best way if you know.

0
source

Source: https://habr.com/ru/post/1348183/


All Articles