ruby-on-rails – 如何在单表继承中运行子类的验证?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 如何在单表继承中运行子类的验证?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在我的申请中,我有一个名为Budget的课程.预算可以是多种类型.例如,我们假设有两个预算:FlatRateBudget和HourlyRateBudget.两者都继承了课堂预算.

这是我到现在为止

class Budget < ActiveRecord::Base
  validates_presence_of :price
end

class FlatRateBudget < Budget
end

class HourlyRateBudget < Budget
  validates_presence_of :quantity
end

在控制台中,如果我这样做:

b = HourlyRateBudget.new(:price => 10)
b.valid?
=> false
b.errors.full_messages
=> ["Quantity can't be blank"]

正如所料.

问题是STI上的“type”字段来自params ..所以我需要做一些像

b = Budget.new(:type => "HourlyRateBudget",:price => 10)
b.valid?
=> true

这意味着rails在超类中运行验证,而不是在设置类型之后实例化子类.

我知道这是预期的行为,因为我正在实例化一个不需要数量字段的类,但是我想知道是否有任何方式告诉rails为子类而不是超级运行验证.

解决方法

您可以使用自定义验证程序来解决此问题,类似于此问题的答案: Two models,one STI and a Validation但是,如果您可以简单地实例化初始化的子类型,那么在这种情况下,您将完全避免使用自定义验证器.

如您所注意到的那样,单独设置类型字段并不会将实例从一种类型更改为另一种类型.虽然ActiveRecord将使用类型字段在从数据库读取对象时实例化正确的类,但以另一种方式进行操作(实例化超类,然后手动更改类型字段)不具有更改对象类型的效果你的应用程序正在运行 – 它不会这样工作.

另一方面,自定义验证方法可以独立检查类型字段,实例化相应类型的副本(基于类型字段的值),然后运行.valid?在该对象上,导致子类的验证以似乎是动态的方式运行,即使它实际上是在进程中创建适当子类的实例.

原文链接:https://www.f2er.com/ruby/271817.html

猜你在找的Ruby相关文章