Examples:
Defining a simple Chain with three steps
class CreateUser
include ::Teckel::Operation::Results
input Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer.optional)
output Types.Instance(User)
error Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))
def call(input)
user = User.new(name: input[:name], age: input[:age])
if user.save
success!(user)
else
fail!(message: "Could not save User", errors: user.errors)
end
end
end
class LogUser
include ::Teckel::Operation::Results
input Types.Instance(User)
output input
def call(usr)
Logger.new(File::NULL).info("User #{usr.name} created")
usr end
end
class AddFriend
class << self
attr_accessor :fail_befriend
end
include ::Teckel::Operation::Results
input Types.Instance(User)
output Types::Hash.schema(user: Types.Instance(User), friend: Types.Instance(User))
error Types::Hash.schema(message: Types::String)
def call(user)
if self.class.fail_befriend
fail!(message: "Did not find a friend.")
else
{ user: user, friend: User.new(name: "A friend", age: 42) }
end
end
end
class MyChain
include Teckel::Chain
step :create, CreateUser
step :log, LogUser
step :befriend, AddFriend
end
result = MyChain.call(name: "Bob", age: 23)
result.is_a?(Teckel::Result) result.success[:user].is_a?(User) result.success[:friend].is_a?(User)
AddFriend.fail_befriend = true
failure_result = MyChain.call(name: "Bob", age: 23)
failure_result.is_a?(Teckel::Chain::StepFailure)
failure_result.step_name failure_result.step
failure_result.failure? failure_result.failure
DB transaction around hook
class CreateUser
include ::Teckel::Operation::Results
input Types::Hash.schema(name: Types::String, age: Types::Coercible::Integer.optional)
output Types.Instance(User)
error Types::Hash.schema(message: Types::String, errors: Types::Array.of(Types::Hash))
def call(input)
user = User.new(name: input[:name], age: input[:age])
if user.save
success!(user)
else
fail!(message: "Could not safe User", errors: user.errors)
end
end
end
class AddFriend
class << self
attr_accessor :fail_befriend
end
include ::Teckel::Operation::Results
input Types.Instance(User)
output Types::Hash.schema(user: Types.Instance(User), friend: Types.Instance(User))
error Types::Hash.schema(message: Types::String)
def call(user)
if self.class.fail_befriend
fail!(message: "Did not find a friend.")
else
{ user: user, friend: User.new(name: "A friend", age: 42) }
end
end
end
LOG = []
class MyChain
include Teckel::Chain
around ->(chain, input) {
result = nil
begin
LOG << :before
FakeDB.transaction do
result = chain.call(input)
raise FakeDB::Rollback if result.failure?
end
LOG << :after
result
rescue FakeDB::Rollback
LOG << :rollback
result
end
}
step :create, CreateUser
step :befriend, AddFriend
end
AddFriend.fail_befriend = true
failure_result = MyChain.call(name: "Bob", age: 23)
failure_result.is_a?(Teckel::Chain::StepFailure)
LOG
failure_result.step_name failure_result.step
failure_result.failure? failure_result.failure