ActiveRecord builds instance of wrong class through a scope targeting an STI class

强颜欢笑 提交于 2020-01-04 06:44:17

问题


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.


回答1:


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.




回答2:


Forget about build for a moment. If you have some LineItem l and you do l.discount you're going to get LineItem instances, not DiscountLineItem instances. If you want to get DiscountLineItem instances, I suggest converting the scope to a method

def self.discount
  where(type: 'DiscountLineItem').map { |l| l.becomes(l.type.constantize) }
end

Now you will get back a collection of DiscountLineItem instances.



来源:https://stackoverflow.com/questions/11387836/activerecord-builds-instance-of-wrong-class-through-a-scope-targeting-an-sti-cla

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!