Teckel
Ruby service classes with enforced1 input, output and error data structure definition.
Installation
Add this line to your application's Gemfile:
gem 'teckel'
And then execute:
$ bundle
Or install it yourself as:
$ gem install teckel
Motivation
Working with Interactor, Trailblazer's Operation and Dry-rb's Transaction and probably a hand full of inconsistent "service objects", I missed a system that:
- provides and enforces well defined input, output and error structures
- makes chaining multiple operation easy and reliable
- is easy to debug
Usage
For a full overview please see the Docs:
class CreateUser
include Teckel::Operation
# DSL style declaration
input Struct.new(:name, :age, keyword_init: true)
# Constant style declaration
Output = ::User
# Well, also Constant style, but using classic `class` notation
class Error
def initialize(message:, status_code:, meta:)
@message, @status_code, @meta = message, status_code, meta
end
attr_reader :message, :status_code, :meta
end
error_constructor :new
def call(input)
user = User.new(name: input.name, age: input.age)
if user.save
success!(user)
else
fail!(
message: "Could not create User",
status_code: 400,
meta: { validation: user.errors }
)
end
end
end
CreateUser.call(name: "Bob", age: 23) #=> #<User @age=23, @name="Bob">
CreateUser.call(name: "Bob", age: 5) #=> #<CreateUser::Error @message="Could not create User", @meta={:validation=>[{:age=>"underage"}]}, @status_code=400>
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/fnordfish/teckel. Feature requests should provide a detailed explanation of the missing or changed behavior, if possible including some sample code.
Please also see DEVELOPMENT.md for planned features and general guidelines.
Footnotes
- 1: Obviously, it's still Ruby and you can cheat. Don’t! ↩