继承的 Trailblazer 操作的契约是否可以更改其超类定义的验证?

Can an inherited Trailblazer operation's contract alter validations defined by its superclass?

当一个Trailblazer操作被继承定义时,它继承它的superclass的契约:

class Create < Trailblazer::Operation
  contract do 
    ... 
  end
  ...
end

class Update < Create
  ...
end

继承的 Trailblazer 操作的合约是否可以更改其超级class定义的验证?

出现这个问题是因为创建操作的契约定义了一个强制性的属性,它需要在更新操作中是可选的:

validates :foo, presence: true

最初的想法是以某种方式反转继承class中的这个定义,但似乎没有办法做到这一点(有可能ignore a 属性 in the subclass (writeable:false - book p61) 但似乎没有办法改变它的有效性标准)。

一种解决方案是在每个操作的合同中使用外部表单。通过将表单提取到外部 class,创建操作将像这样包含和扩充它:

contract Form do
  validates :upload, presence: true
end 

更新更新将简单地包含它:

contract Form

现在 Create 中添加的验证不适用于 Update

您可以通过向验证器添加 if 语句来实现您想要的结果:

class Create < Trailblazer::Operation
  contract do
    validates :upload, presence: true, if: Proc.new{ |record| !record.persisted? }
  end
end
class Update < Create
end

仅当记录尚未保存到数据库时才运行验证,因此在更新操作期间将跳过验证。 (假设您正在使用 ActiveModel 并遵循正常的 CRUD 使用模式。)