I would like to be able to call the build
method on a scope that targets a certain class of model via its STI type, and have ActiveRecord build an instance of the correct class.
class LineItem < ActiveRecord::Base
scope :discount, where(type: 'DiscountLineItem')
end
class DiscountLineItem < LineItem; end
> LineItem.discount.build # Expect an instance of DiscountLineItem here
=> #<LineItem ...>
Here, I expected an instance of DiscountLineItem
, not an instance of LineItem
.
Even though ActiveRecord doesn't instantiate the object as the right class, it does set the type correctly. You basically have two ways around this:
1) Create the object and then reload it from the database:
item = LineItem.discount.create(attrs...)
item = LineItem.find(item.id)
2) Use the STI class and build the object directly from it:
DiscountLineItem.build
With all that ActiveRecord can do, this does seem like kind of a senseless limitation and might not be too hard to change. Now you've piqued my interested :)
Update:
This was recently added to Rails 4.0 with the following commit message:
Allows you to do BaseClass.new(:type => "SubClass") as well as parent.children.build(:type => "SubClass") or parent.build_child to initialize an STI subclass. Ensures that the class name is a valid class and that it is in the ancestors of the super class that the association is expecting.