Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/waiting-for-dev/kwork
Composable service objects
https://github.com/waiting-for-dev/kwork
Last synced: 27 days ago
JSON representation
Composable service objects
- Host: GitHub
- URL: https://github.com/waiting-for-dev/kwork
- Owner: waiting-for-dev
- License: mit
- Created: 2022-10-04T11:21:10.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2023-09-19T14:09:30.000Z (about 1 year ago)
- Last Synced: 2024-05-02T00:04:22.284Z (6 months ago)
- Language: Ruby
- Homepage:
- Size: 128 KB
- Stars: 1
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Kwork
Kwork is a library for building business transactions in Ruby designed to:
- Be written in a declarative and chainable way.
- Decouple individual operations from business transactions.
- Injecting operations for testing purposes or reusability.
- Be used with different result types (e.g. `Kwork::Result`,
`Dry::Monads::Result`, `Dry::Monads::Maybe`...).
- Provide transactional safety for different database adapters (e.g.,
`ROM`, `ActiveRecord`...).## Installation
Add this line to your application's Gemfile:
```ruby
gem 'kwork', github: 'waiting-for-dev/kwork'
```And then execute:
$ bundle install
## Usage
Using [`dry-auto_inject`](https://dry-rb.org/gems/dry-auto_inject/1.0/) & [`dry-monads`](https://dry-rb.org/gems/dry-monads/1.6/).
```ruby
require "kwork"class CheckOutOrder
include Kwork[adapter: :result]
include Deps[:update_line_items, :update_order, :calculate_best_prices, :enqueue_order_completed_email]
def call(order_id, attrs)
attrs = step validate(attrs)
line_items = step update_line_items.(order_id, attrs[:line_items])
order = step update_order.(order_id, attrs.except(:line_items))
step calculate_best_prices.(order:, line_items:)
step enqueue_order_completed_email.(order)
success(order)
end
private
def validate(attrs)
# ...
end
endinclude Dry::Monads[:result]
case CheckoutOrder.new
in Success[message]
puts message
in Failure[error]
puts error
end
```### Advanced usage
You can leverage [transactable](https://alchemists.io/projects/transactable) to elegantly use the Railway pattern for data transformation or the whole transactional workflow. For now, it only works with `Dry::Monads::Result` adapter:
```ruby
class CreateUser
include Kwork[adapter: :result]
include Deps["user_repo", "validate_user"]
include Dry::Monads[:result]
DEFAULT_USER_ATTRS = {
country: :us,
currency: :usd
}def call(user_attrs)
user = pipe user_attrs,
merge(DEFAULT_USER_ATTRS),
method(:validate_user)step create_user(user)
endprivate
def create_user(user)
Success(user_repo.create(user))
end
end
```### Extensions
More often than not, a business transaction needs to be wrapped within a database transaction. To support this use case, Kwork gives you the ability to extend the transaction callback so you can wrap it with your own code. A couple of extensions are shipped by default, but you can easily build your own.
#### ROM
You need to add [rom](https://rom-rb.org/) to your `Gemfile` to use it. When this extension is used, the Kwork transaction is wrapped within a database transaction, which is rolled back in the case of returning a failure.
```ruby
require "kwork"
require "kwork/extensions/rom"rom = # ROM container
class AddUser
include Kwork[
extension: Kwork::Extensions::ROM[rom, :default] # :default is the name of the gateway
]
# ...
end
```#### ActiveRecord
On a Rails application, you can use the ActiveRecord extension. The raw Kwork transaction will be wrapped within a database transaction, and it'll be rolled back in case of returning a failure.
```ruby
require "kwork"
require "kwork/extensions/active_record"class AddUser
include Kwork[
extension: Kwork::Extensions::ActiveRecord
]
# ...
end
```#### Custom extensions
Custom extensions are just anything responding to `#call` accepting the Kwork transaction callback. You only need to ensure that you respond the result of executing that callback. Take into account that the callback will return an instance of `Kwork::Result`, regardless of the adapter in use. That ensures fully operability with any result type.
```ruby
require "kwork"MyExtension = lambda do |callback|
callback.().tap do |result|
do_something if result.success?
end
endclass AddUser
include Kwork[
extension: MyExtension
]
# ...
end
```## 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]/kwork. 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]/kwork/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 Kwork project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/kwork/blob/master/CODE_OF_CONDUCT.md).