A simple, standardized way to build and use Service Objects (aka Commands) in Ruby
- Ruby 2.0+
Add this line to your application's Gemfile:
gem'simple_command'And then execute:
$ bundle
Or install it yourself as:
$ gem install simple_command
Here's a basic example of a command that authenticates a user
# define a command classclassAuthenticateUser# put SimpleCommand before the class' ancestors chainprependSimpleCommandincludeActiveModel::Validations# optional, initialize the command with some argumentsdefinitialize(email,password)@email=email@password=passwordend# mandatory: define a #call method. its return value will be available# through #resultdefcallifuser=User.find_by(email: @email)&.authenticate(@password)returnuserelseerrors.add(:base,:failure)endnilendendin your locale file
# config/locales/en.ymlen:
activemodel:
errors:
models:
authenticate_user:
failure: Wrong email or passwordThen, in your controller:
classSessionsController < ApplicationControllerdefcreate# initialize and execute the command# NOTE: `.call` is a shortcut for `.new(args).call`command=AuthenticateUser.call(session_params[:email],session_params[:password])# check command outcomeifcommand.success?# command#result will contain the user instance, if foundsession[:user_token]=command.result.secret_tokenredirect_toroot_pathelseflash.now[:alert]=t(command.errors.full_messages.to_sentence)render:newendendprivatedefsession_paramsparams.require(:session).permit(:email,:password)endendMake the spec file spec/commands/authenticate_user_spec.rb like:
describeAuthenticateUserdosubject(:context){described_class.call(username,password)}describe'.call'docontext'when the context is successful'dolet(:username){'correct_user'}let(:password){'correct_password'}it'succeeds'doexpect(context).tobe_successendendcontext'when the context is not successful'dolet(:username){'wrong_user'}let(:password){'wrong_password'}it'fails'doexpect(context).tobe_failureendendendend- Fork it ( https://github.com/nebulab/simple_command/fork )
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request