TypedOperation
An implementation of a Command pattern, which is callable, and can be partially applied (curried).
Inputs to the operation are specified as typed attributes using the param
method.
Result format of the operation is up to you, but plays nicely with Dry::Monads
.
Examples:
A base operation class:
class ApplicationOperation < ::TypedOperation::Base
include Dry::Monads[:result, :do]
param :initiator, ::RegisteredUser, allow_nil: true
private
def succeeded(value)
Success(value)
end
def failed_with_value(value, message: "Operation failed", error_code: nil)
failed(error_code || self.class.operation_key, , value)
end
def (, error_code: nil)
failed(error_code || self.class.operation_key, )
end
def failed(error_code, = "Operation failed", value = nil)
Failure[error_code, , value]
end
def failed_with_code_and_value(error_code, value, message: "Operation failed")
failed(error_code, , value)
end
end
A simple operation:
class TestOperation < ::ApplicationOperation
param :foo, String
param :bar, String
param :baz, String, convert: true
def prepare
# to setup (optional)
puts "lets go!"
end
def call
succeeded("It worked!")
# failed_with_message("It failed!")
end
end
TestOperation.(foo: "1", bar: "2", baz: 3)
# => Success("It worked!")
TestOperation.with(foo: "1").with(bar: "2")
# => #<TypedOperation::PartiallyApplied:0x000000014a655310 @applied_args={:foo=>"1", :bar=>"2"}, @operation=TestOperation>
TestOperation.with(foo: "1").with(bar: "2").with(baz: 3)
# => <TypedOperation::Prepared:0x000000012dac6498 @applied_args={:foo=>"1", :bar=>"2", :baz=>3}, @operation=TestOperation>
TestOperation.with(foo: "1").with(bar: "2").with(baz: 3).call
# => Success("It worked!")
TestOperation.with(foo: "1").with(bar: "2").with(baz: 3).operation
# => <TestOperation:0x000000014a0048a8 @__attributes=#<TestOperation::TypedSchema foo="1" bar="2" baz="3">>
Installation
Add this line to your application's Gemfile:
gem "typed_operation"
And then execute:
$ bundle
Or install it yourself as:
$ gem install typed_operation
Add an ApplicationOperation
to your project
bin/rails g typed_operation:install
Use the --dry_monads
switch to include Dry::Monads[:result]
into your ApplicationOperation
(don't forget to also
add gem "dry-monads"
to your Gemfile)
bin/rails g typed_operation:install --dry_monads
Generate a new Operation
bin/rails g typed_operation TestOperation
You can optionally specify the directory to generate the operation in:
bin/rails g typed_operation TestOperation --path=app/operations
The default path is app/operations
.
The generator will also create a test file.
Contributing
Contribution directions go here.
License
The gem is available as open source under the terms of the MIT License.