Operation: Contract
Last updated 02 December 2016 trailblazer v1.1 v2.0Operation: Contract
The operation’s contract is one of the pivotal elements in Trailblazer. It integrates the deserialization and validation into your service object.
[DOCS STILL UNDER CONSTRUCTION]
Composition
Contracts don’t have to map to one model, only.
If your contract embraces several models using Composition, you can easily pass the composition hash via validate. Note that composition is a Reform feature. Do not forget the on: option when defining your compositional mapping.
class Create < Trailblazer::Operation
contract do
include Reform::Form::Composition
property :id, on: :comment
property :name, on: :author
end
def process(params)
comment = Comment.find(params[:id])
author = comment.author
validate(params, comment: comment, author: author)
end
end
The second argument to validate is the contract’s model. As per Reform’s API, for compositions this must be a hash.
Injection
It is possible to inject additional dependencies into the contract, which are not part of the original model(s). This often is a current_user or the operation instance itself.
Those dependencies have to be virtual properties in the contract. They can then be passed as the third argument to validate.
class Create < Trailblazer::Operation
contract do
property :current_user, virtual: true
property :operation, virtual: true
end
def process(params)
validate(params, model,
current_user: params[:current_user],
operation: self) do |f|
end
end
end
The same semantics apply to contract.
contract! Method
To automate injection or composition, you can override Operation#contract!. Note that you will still need to specify the virtual properties in the contract as above.
class Create < Trailblazer::Operation
private
def contract!(model=nil, contract_class=nil)
contract_class ||= self.class.contract_class
@contract ||= contract_class.new(model,
current_user: @current_user,
operation: self)
end
Or if you don’t require arguments when calling contract, simply use:
class Create < Trailblazer::Operation
private
def contract! *args
@contract ||= self.class.contract_class.new(nil, operation: self)
end
