Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/adham90/command_service_object
:package: :octopus: command_service_object gem helps you to generate service and command objects using rails generator.
https://github.com/adham90/command_service_object
command domain-driven-design generator rails rails-generator service service-object
Last synced: 3 months ago
JSON representation
:package: :octopus: command_service_object gem helps you to generate service and command objects using rails generator.
- Host: GitHub
- URL: https://github.com/adham90/command_service_object
- Owner: adham90
- License: mit
- Created: 2019-04-10T00:19:19.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-03-08T21:46:21.000Z (over 1 year ago)
- Last Synced: 2024-07-19T18:41:53.888Z (4 months ago)
- Topics: command, domain-driven-design, generator, rails, rails-generator, service, service-object
- Language: Ruby
- Homepage: https://rubygems.org/gems/command_service_object
- Size: 143 KB
- Stars: 9
- Watchers: 2
- Forks: 0
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# CommandServiceObject
Rails Generator for command service object.
## Theory
[Command Design Pattern](https://en.wikipedia.org/wiki/Command_pattern) consists of `Command Object` and `Service Object` (Executor), Command object is responsible for containing `Client` requests and run input validations on it to ensure that the request is valid and set default values, then `Service Object` applies the business logic on that command.
### Implementation
Service consists of several objects { `Command Object` `Usecase Object` And `Error Object` (business logic error) }.
- **[Command](https://en.wikipedia.org/wiki/Command_pattern):** the object that responsible for containing `Client` requests and run input validations it's implemented using [Virtus](https://github.com/solnic/virtus) gem and can use `activerecord` for validations and it's existed under `commands` dir.
- **Usecase:** this object responsible for executing the business logic, Every `usecase` should execute one command type only so that command name should be the same as usecase object name, usecase object existed under 'usecases` dir.
- **Micros:** Small reusable logic under the same service.
- **Externals:** Simple ruby module works as a service interface whenever you wanna call any external service or even service that lives under the same project you should use it.
- **Queries:** This dir is the only entry point for you to get any data form a service.
- **Listeners:** An event listener that waits for an event outside the service to occur.
- **Entities:** Many objects are not fundamentally defined by their attributes, but rather by a thread of continuity and identity.### Result Object
In case of successful or failure `ApplicationService` the responsible object for all services will return `service_result` object this object contain `value!` method containing successful call result, and `errors` method containing failure `errors` objects.
### Helpers:
- Fail: You can use `fail!` helper to raise business logic failures, ex: `fail!('user should not have any active cards')`.
- Check: To do business logic validations you can use `check!` helper ex: `check!('user should not have any active cards') { user.active_cards.empty? }`, if the given block returns false then it will raise fail! with the given message.> You can check if the result successful or not by using `ok?` method.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'command_service_object'
```And then execute:
`bundle`
Or install it yourself as:
`gem install command_service_object`
Next, you need to run the generator:
`rails generate service:install`
## Usage
$ rails g service [service_name] [usecases usecases]
### Generate Service ex
$ rails g service auth login
output```bash
app/services/
├── application_service.rb
├── auth_service
│ ├ external/
│ ├── commands
│ │ └── login.rb
│ └── usecases
│ ├── login.rb
│ └── micros
├── case_base.rb
└── service_result.rb
```### Generate micros ex
$ rails g service:micro auth generate_jwt_token_for
```bash
app/services/
├── auth_service
│ └── usecases
│ └── micros
│ └── generate_jwt_token_for.rb
``````ruby
# app/services/auth_service/usecases/micros/generate_jwt_token_for.rbmodule PaymentService::Usecases::Micros
class GenerateJwtTokenFor < CaseBase
def call
#
end
end
end
```then you can edit command params
> you can read [Virtus gem docs](https://github.com/solnic/virtus) for more info.```ruby
# app/services/auth_service/commands/login.rb
# frozen_string_literal: truemodule AuthService::Commands
class Login < CommandBase
# You can read Virtus gem doc for more info.
# https://github.com/solnic/virtus# Attributes
# attribute :REPLACE_ME, String# Validations
# validates :REPLACE_ME, presence: true
end
end
```and then add your business logic
```ruby
# app/services/auth_service/usecases/login.rb
# frozen_string_literal: truemodule AuthService::Usecases
class Login < CaseBase
include CommandServiceObject::Hooks
micros :generate_jwt_token_for
#
# Your business logic goes here, keep [call] method clean by using private
# methods for Business logic.
#
def call
token = generate_jwt_token_for(cmd.user)
replace_meoutput
enddef output
# return entity object
end# This method will run if call method raise error
def rollback
# rollback logic
end
def allowed?
# policies loginc for issuer
# ex:
#
# return false if issuer.role != :admintrue
endprivate
def replace_me
# [business logic]
end
end
end
```### External APIs or Services
You can wrap external apis or services under `external/` dir
#### ex
```ruby
module External
module StripeService
extend selfdef charge(customer:, amount:, currency:, description: nil)
Stripe::Charge.create(
customer: customer.id,
amount: (round_up(amount, currency) * 100).to_i,
description: description || customer.email,
currency: currency
)
end
end
end
```usage from controller
```ruby
class AuthenticationController < ApplicationController
default_service :auth_servicedef Login
cmd = command.new(params) # AuthService::Commands::Login.new
result = execute(cmd)if result.ok?
render json: result.value!.as_json, status: 201
else
render json: { message: result.error }, status: 422
end
end
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 tags, 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/adham90/command_service_object. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
## 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 CommandServiceObject project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/adham90/command_service_object/blob/master/CODE_OF_CONDUCT.md).