Comandor
Service Object (Interactor, Command) are used to encapsulate your application's business logic. To keep Singe Responsibility principle each service object represents only one thing that your application does.
Installation
Add this line to your application's Gemfile:
gem 'comandor'
And then execute:
$ bundle
Or install it yourself as:
$ gem install comandor
Usage
# Your Service class
class DepositCreate
extend Comandor # here we are!
# Initialize object with some arguments as usual Ruby object (of course it's optional)
def initialize(user, amount)
@user = user
@amount = amount
end
# Define your business logic by implementing the #perform method.
# Results of call will be in the #result method of instance.
# #perform will return the instance of your Class.
# You can use the #success? method to check if results it is a valid
# or fail? (failed?) if it’s invalid.
# And you can get all errors with #errors method.
def perform
# .error method adds message to the :amount field
return error(:amount, 'Deposit amount should be more than $100') if @amount < 100
create_deposit
end
private
def create_deposit
@user.deposits.create(amount: @amount)
end
end
In the Controller:
class DepositsController < ApplicationController
def create
deposit_create = DepositCreate.new(current_user, 100).perform
if deposit_create.success?
redirect_to root_path, notice: 'Deposit created'
else
redirect_to root_path, alert: deposit_create.errors[:amount].join("\n")
end
end
end
or just
deposit_create = DepositCreate.perform(current_user, 100)
Another option to call #perform with any arguments
# Another Service class
class InvoiceSend
extend Comandor # here we are!
def perform(email = nil, amount = 0)
return error(:amount, 'Deposit amount should be more than $100') if amount < 100
return error(:email, 'E-mail is blank') unless email
create_and_send_invoice(email, amount)
end
private
def create_and_send_invoice(email, amount)
# ... your another code is here
end
end
in use:
delivery = InvoiceSend.new.perform('renat@aomega.co', 100)
if delivery.success?
# all good
puts delivery.result
else
# Houston, we have a problem
puts deliver.errors.inspect
end
or
delivery = InvoiceSend.perform('renat@aomega.co', 100)
state methods:
# was last .perform call success or not
delivery.success?
# results of .perform call
delivery.result
# Hash of errors
#{
# 'field1': ['error message 1', 'error message 2'],
# 'field2': ['error message 3']
#}
delivery.errors
one more example:
class User::Registration
attr_reader :user, :bank_account
extend Comandor
def initialize(params)
@params = params
end
def perform
create_user! && create_bank_account!
end
private
def create_user!
@user = User.new(@params)
return true if @user.save
error(:user, @user.errors.to_a)
false
end
def create_bank_account!
@bank_account = Bank::Account.new(user: @user)
return true if @bank_account.save
error(:bank_account, @bank_account.errors.to_a)
false
end
end
example of using:
registration = User::Registration.new(user_params).perform
if registration.success?
puts registration.user.inspect
puts registration.bank_account.inspect
else
puts registration.errors
end
transaction!
wrapper around perform
method look like
class User::Message
extend Comandor
transaction! 'ActiveRecord::Base.transaction'
def perform(user)
@user = user
create_message! && send_message! && write_log!
end
#...
end
User::Message.perform(User.first)
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.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/mpakus/comandor. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
License
The gem is available as open source under the terms of the MIT License.