Let’s say I have a class like:
class Basket < ActiveRecord::Base
has_many :fruits
Where “fruits” is an STI base class having subclasses like “apples”, “oranges”, etc…
I’d like to be able to have a setter method in Basket like:
def fruits=(params)
unless params.nil?
params.each_pair do |fruit_type, fruit_data|
fruit_type.build(fruit_data)
end
end
end
But, obviously, I get an exception like:
NoMethodError (undefined method `build' for "apples":String)
A workaround I thought of works like this:
def fruits=(params)
unless params.nil?
params.each_pair do |fruit_type, fruit_data|
"#{fruit_type}".create(fruit_data.merge({:basket_id => self.id}))
end
end
end
But that causes the Fruit STI object to be instantiated before the Basket class, and so the basket_id key is never saved in the Fruit subclass (because basket_id doesn’t exist yet).
I’m totally stumped. Anyone have any ideas?
Instead of adding a setter method in Basket, add it in Fruit:
Now you can pass the type in when you build the object through an association:
Note that you can’t assign
:typethis way, since it is protected from mass assignment.EDIT
Oh, you wanted to run different callbacks depending on the subclass? Right.
You could do this:
or define a
has_manyassociation for each type:then