ActiveRecord通过针对STI类的作用域构建错误类的实例
我希望能够通过其STI类型在一个以某类模型为目标的作用域上调用build
方法,并让ActiveRecord构建一个正确类的实例。
class LineItem < ActiveRecord::Base scope :discount, where(type: 'DiscountLineItem') end class DiscountLineItem LineItem.discount.build # Expect an instance of DiscountLineItem here => #
在这里,我期待一个DiscountLineItem
的实例,而不是LineItem
一个实例。
即使ActiveRecord没有将对象实例化为正确的类,它也会正确设置类型。 你基本上有两种解决方法:
1)创建对象,然后从数据库重新加载它:
item = LineItem.discount.create(attrs...) item = LineItem.find(item.id)
2)使用STI类并直接从它构建对象:
DiscountLineItem.build
有了ActiveRecord可以做的所有事情,这看起来似乎是一种无意义的限制,可能不会太难改变。 现在你已经引起了我的兴趣:)
更新:
最近使用以下提交消息将其添加到Rails 4.0 :
允许您执行BaseClass.new(:type =>“SubClass”)以及parent.children.build(:type =>“SubClass”)或parent.build_child来初始化STI子类。 确保类名是一个有效的类,并且它位于关联所期望的超类的祖先中。
暂时忘记build
。 如果您有一些LineItem
l
并且您执行l.discount
那么您将获得LineItem
实例,而不是DiscountLineItem
实例。 如果你想获得DiscountLineItem
实例,我建议将范围转换为方法
def self.discount where(type: 'DiscountLineItem').map { |l| l.becomes(l.type.constantize) } end
现在,您将获得一个DiscountLineItem
实例的集合。