https://github.com/benpickles/operatic
🗣️ A minimal standard interface for your Ruby operations
https://github.com/benpickles/operatic
ruby
Last synced: about 2 months ago
JSON representation
🗣️ A minimal standard interface for your Ruby operations
- Host: GitHub
- URL: https://github.com/benpickles/operatic
- Owner: benpickles
- License: mit
- Created: 2019-09-05T13:08:58.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2025-08-12T15:18:17.000Z (9 months ago)
- Last Synced: 2025-10-08T01:29:07.815Z (7 months ago)
- Topics: ruby
- Language: Ruby
- Homepage: https://www.benpickles.com/articles/87-announcing-operatic
- Size: 55.7 KB
- Stars: 23
- Watchers: 2
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Operatic
[](https://github.com/benpickles/operatic)
A minimal standard interface for your operations.
## Installation
Add Operatic to your application's Gemfile and run `bundle install`.
```ruby
gem 'operatic'
```
## Usage
An Operatic class encapsulates an operation and communicates its status via a result object. As well as being a `#success?` or `#failure?` data can also be attached to the result via `#success!`, `#failure!`, or during the operation's execution.
```ruby
class SayHello
include Operatic
# Readers for instance variables defined in `.call`.
attr_reader :name
# Declare convenience data accessors.
data_attr :message
def call
# Exit the method and mark the operation as a failure.
return failure! unless name
# Mark the operation as a success and attach further data.
success!(message: "Hello #{name}")
end
end
result = SayHello.call(name: 'Dave')
result.class # => Operatic::Success
result.failure? # => false
result.success? # => true
result.message # => "Hello Dave"
result[:message] # => "Hello Dave"
result.to_h # => {:message=>"Hello Dave"}
result = SayHello.call
result.class # => Operatic::Failure
result.failure? # => true
result.success? # => false
result.message # => nil
result[:message] # => nil
result.to_h # => {}
```
A Rails controller might use Operatic like this:
```ruby
class HellosController < ApplicationController
def create
result = SayHello.call(name: params[:name])
if result.success?
render plain: result.message
else
render :new
end
end
end
```
## Pattern matching
An Operatic result also supports pattern matching allowing you to match over a tuple of the result class and its data:
```ruby
case SayHello.call(name: 'Dave')
in [Operatic::Success, { message: }]
# Result is a success, do something with the `message` variable.
in [Operatic::Failure, _]
# Result is a failure, do something else.
end
```
Or match solely against its data:
```ruby
case SayHello.call(name: 'Dave')
in message:
# Result has the `message` key, do something with the variable.
else
# Do something else.
end
```
Which might be consumed in Rails like this:
```ruby
class HellosController < ApplicationController
def create
case SayHello.call(name: params[:name])
in [Operatic::Success, { message: }]
render plain: message
in [Operatic::Failure, _]
render :new
end
end
end
```
## Development
Run the tests with:
```
bundle exec rspec
```
Generate Yard documentation with:
```
bundle exec yardoc
```
## License
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
## Code of Conduct
Everyone interacting in the Operatic project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/benpickles/operatic/blob/main/CODE_OF_CONDUCT.md).