Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/andriy-baran/nina
https://github.com/andriy-baran/nina
Last synced: 20 days ago
JSON representation
- Host: GitHub
- URL: https://github.com/andriy-baran/nina
- Owner: andriy-baran
- License: mit
- Created: 2023-05-22T07:53:55.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2024-05-02T08:24:45.000Z (9 months ago)
- Last Synced: 2024-12-08T14:19:34.335Z (about 1 month ago)
- Language: Ruby
- Size: 355 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- 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
# Nina
[![Gem Version](https://badge.fury.io/rb/nina.svg)](https://badge.fury.io/rb/nina)
[![Maintainability](https://api.codeclimate.com/v1/badges/435ee6e0ae846e9deb88/maintainability)](https://codeclimate.com/github/andriy-baran/nina/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/435ee6e0ae846e9deb88/test_coverage)](https://codeclimate.com/github/andriy-baran/nina/test_coverage)A tool that helps implement the Builder pattern in your code in more deleclarative way.
https://github.com/andriy-baran/toritori## Installation
Install the gem and add to the application's Gemfile by executing:
$ bundle add nina
If bundler is not being used to manage dependencies, install the gem by executing:
$ gem install nina
## Usage
Let's define two builders: main and secondary
```ruby
Params = Class.new
Query = Class.new
Command = Class.newA = Struct.new(:a)
B = Struct.new(:b)
C = Struct.new(:c)class Flow
include Ninabuilder :main do
factory :params, produces: Params
factory :query, produces: Query
factory :command, produces: Command
endbuilder :secondary do
factory :params, produces: A
factory :query, produces: B
factory :command, produces: C
end
end
```
Each builder has three factories: params, query, and command. Please check https://github.com/andriy-baran/toritori for related documentation.With this setup we are able to compose objects in two different ways. Taking the definition block as an ordered list we can traverse it `top->bottom` or `bottom->top` connecting objects at each step
Wrapping
![](https://github.com/andriy-baran/nina/blob/master/assets/wrap.gif?raw=true)
Nesting
![](https://github.com/andriy-baran/nina/blob/master/assets/nest.gif?raw=true)
Lets explore what we have as a result
```ruby
# Wrapping strategy
builder = abstract_factory.main_builder
instance = builder.wrap do |build|
# This block controlls order of building process steps
# Allows you to provide initialization attributes
# And specify only things you need to be added
build.params # The most nested object;
q = build.query # query will get a reader to params
build.command if i_need_this? # Top level object; command will get a reader to query
build.query == q # memoization do not allow creation of objects multiple times
build.query(1, 2, 3) # instead it returns first object no matter what parameters you provided later
end
instance # => #
instance.query # => #
instance.query.params # => ## Nesting strategy
builder = abstract_factory.secondary_builder
instance = builder.nest do |build|
build.params # Top level object
build.query # query will get a reader to params
build.command # The most nested object; query will get a reader to command
end
instance # => #
instance.query # => #
instance.query.command # => #
```### Delegation
We may apply delegation techique from OOD to expose methods of deeper layers
```ruby
builder = abstract_factory.secondary_builder
instance = builder.nest(delegate: true) do |build|
build.params
build.query
build.command
end
instance.a # => nil
instance.b # => nil
instance.c # => nil
instance.query.c # => nil
```
If you need provide an initalization parameters for the objects
```ruby
instance = builder.wrap(delegate: true) do |b|
# b.params(1, 2) => ArgumentError
b.params(1)
b.query(2)
b.command(3)
end
instance.a # => 1
instance.b # => 2
instance.c # => 3
```### Top level API
If you have some objects and just want to link them you can use following methods
```ruby
setup = { params: params, query: query, command: command }
Nina.link(setup, delegate: true) do |name, object| # => params.query.command
# optionally do something
endNina.reverse_link(setup, delegate: false) do |name, object| # => command.query.params
# optionally do something
end
```### Callbacks
To do something between stages (after creation of object)
```ruby
builder_with_callbacks = builder.with_callbacks do |c|
c.params { _1.a = 1 }
c.params { _1.a += 3 }
c.params { _1.a += 2 }
c.query { _1.b = 2 }
end
instance = builder_with_callbacks.wrap
instance.query.params.a # => 6
instance.query.b # => 2
instance.c # => nil
```We are copying callbacks from builder if had some defined
```ruby
builder_with_callbacks = builder.with_callbacks do |c|
c.params { _1.a = 1 }
end
builder_with_callbacks_with_callbacks = builder_with_callbacks.with_callbacks do |c|
c.params { _1.a += 1 }
end
instance = builder_with_callbacks.wrap
instance.a # => 2
```## 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.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/nina. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/nina/blob/master/CODE_OF_CONDUCT.md).
## 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 Nina project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/nina/blob/master/CODE_OF_CONDUCT.md).