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

160 views Asked by At

When a Trailblazer operation is defined by inheritance, it inherits its superclass's contract:

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

class Update < Create
  ...
end

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

This question arose because a create operation's contract defined a mandatory property that needed to be optional in the update operation:

validates :foo, presence: true

The initial thought was to somehow reverse this definition in the inherited class but there didn't appear to be a way to do this (it is possible to ignore a property in the subclass (writeable:false - book p61) but there appears to be no way to change its validity criteria).

2

There are 2 answers

0
starfry On BEST ANSWER

One solution is to use an external form in each operation's contract. By extracting the form to an external class, the create operation would include and augment it like so:

contract Form do
  validates :upload, presence: true
end 

and the update uperation would include it simply as:

contract Form

Now the validations added in Create don't apply in Update.

0
Jeremy Weathers On

You can achieve your desired result by adding an if statement to the validator:

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

This runs the validation only if the record has not yet been persisted to the database, so it will be skipped during the Update operation. (This assumes that you're using ActiveModel and following the normal CRUD usage pattern.)