https://github.com/tstaetter/nanites
Command pattern framework for Ruby
https://github.com/tstaetter/nanites
command-pattern ruby
Last synced: 5 months ago
JSON representation
Command pattern framework for Ruby
- Host: GitHub
- URL: https://github.com/tstaetter/nanites
- Owner: tstaetter
- License: mit
- Created: 2021-11-12T02:25:23.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2022-05-31T13:31:24.000Z (about 4 years ago)
- Last Synced: 2025-08-10T03:37:56.771Z (11 months ago)
- Topics: command-pattern, ruby
- Language: Ruby
- Homepage: https://github.com/tstaetter/nanites
- Size: 71.3 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/tstaetter/nanites/actions/workflows/main.yml)
# Nanites - tiny command pattern framework for Ruby
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'nanites', github: 'tstaetter/nanites', branch: 'main'
```
And then execute:
$ bundle install
When available on rubygems.org, you can install it yourself as:
$ gem install nanites
TODO: Push gem to rubygems when initial release is ready
## Usage
Using the commands is pretty straight forward (see specs/support for more examples).
```ruby
class MyCommand < Nanites::Commands::Command
def execute(**params)
# your code here
if all_went_well
success success_payload
else
error error_payload
end
end
end
# Be sure to only use the class method #execute, it ensures save execution
result = MyCommand.execute some_payload
puts result.option if result.success?
# => Nanites::Some @value=
```
Result values are always wrapped in an ```Nanites::Option``` object which
either is a ```Nanites::Some``` indicating some return value is available or
```Nanites::None``` for no value.
This is done in order to not having the hassle to deal with ```nil``` values. This
approach is inspired by the Option type in [Rust](https://www.rust-lang.org/).
### Compounds
Compounds can be used to combine several commands.
A little example:
```ruby
cmd1 = SomeUsefulCommand.new payload
cmd2 = SomeAnalyticsCommand.new payload
compound = Nanites::Commands::Compound.new cmd1, cmd2
context = compound.execute
# => 'context' is a hash containing the execution results of each command with the commands ID as key
```
### Specialized compounds
There are some specials compounds as well, e.g. ```FirstSomeCompound``` returning the first result option which is
a ```Some```, or ```MatchSomeCompound``` returning only results of commands returning ```Some``` options.
For a full list of special compounds see ```lib/nanites/compounds```. Implementing your own specialized compound is
as easy as the following (taken from ```lib/nanites/compounds/match_some_compound.rb```):
```ruby
class MatchSomeCompound < Compound
def initialize(*nanites)
super
@filter = ->(result) { result.option.some? }
end
end
```
The magic happens here in the line ```@filter = ->(result) { result.option.some? }``` defining lambda checking the result.
The filter is applied within the parent class ```execute``` method, getting passed each command result.
### Some and None
```Some``` and ```None``` are both descendants of ```Option```. Each call of ```Nanites::Commands::Command#execute``` will
return either a ```Some``` or ```None```, indicating that the call returns some value, or no value resp.
When using those values, calling ```None#value``` will always return nil. If you need to have an error raised, use ```None#value!```.
Taking the example from the [above code](#command-section), the behaviour is as follows:
```ruby
puts result.option.value
# => will return some value if result.success? is true, nil otherwise
puts result.option.value!
# => will return some value if result.success? is true, raise a Nanites::Errors::ValueError otherwise
```
## Development
`rake spec` to run the tests.
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/tstaetter/nanites.