Rails在update_attributes上进行STI子类验证

时间:2013-01-14 17:45:25

标签: ruby-on-rails ruby sti subclass

我想知道在执行STI时是否有办法使用update_attributes,根据新的类类型验证属性?

例如假设我有:

class A < ActiveRecord::Base
end
class B < A
    validates :attribute_z, :presence => true
end 
class C < A
    validates :attribute_x, :presence => true
    validates :attribute_y, :presence => true 
end

如果我运行(实现rails的方式):

b = A.find('b-id')
b.update_attributes({ 'type' => 'C', :attribute_x => 'present', :attribute_y => 'present', :attribute_z => nil }) # will return false with errors on 'attribute_z must be present'

我尝试过#becomes

b = A.find('b-id')
b = b.becomes(C)
b.update_attributes({ 'type' => 'C', :attribute_x => 'present', :attribute_y => 'present', :attribute_z => nil })
# this works partially, because the validations are ok but when i look to console i get something like: 
UPDATE "as" SET "type" = 'c', "attribute_z" = NULL, "attribute_y' = 'present', 'attribute_x' = 'present' WHERE "as"."type" IN ('C') AND "as"."id" = 'b-id' 
# which is terrible because it's looking for a record of B type on the C types.

2 个答案:

答案 0 :(得分:0)

与此主题Callback for changed ActiveRecord attributes?结盟,您可以捕获对type属性所做的任何赋值,并使用become方法使“self”成为不同的类(A,B或C)。因此,无论何时使用find方法,它都会使用来自数据库的数据(由'b-id'标识)填充新的新模型实例,并且如果需要,它将自动强制转换模型实例到另一种类型。

这对你有帮助吗?

答案 1 :(得分:0)

我已经提出了一个解决方案:https://gist.github.com/4532583,因为条件是由rails内部添加的(https://github.com/rails/rails/blob/master/activerecord/lib/active_record/inheritance.rb #L15)我创建了一个新的“update_attributes”方法,如果给出了类型,它会改变类型。 :)

相关问题