GL::Command
GL::Command is an implementation of the Command Pattern to encapsulate business logic.
The idea is to avoid bloat in Controllers and reduce coupling between models.
Installation
Add the following line to your Gemfile:
gem 'gl-command'
Download and install the gem:
bundle install
Interface
Basic use case
class SomeController
def index
result = DoComplexCommand.call
end
end
class DoComplexCommand
include GL::Command
def call
... complex business logic ...
end
end
Providing data
The call method accepts a hash of parameters as context. The Command has access to these parameters via the the context
attribute.
class SomeController
def index
result = DoComplexCommand.call(page: params[:page],
sort: params[:sort])
end
end
class DoComplexCommand
include GL::Command
def call
BusinessObject.method_call(offset: context.page * 50,
ordering_by: context.sort)
... complex business logic ...
end
end
Returning data
The parameters of the call
method get converted into a GL::Context
.
class SomeController
def index
result = DoComplexCommand.call(page: params[:page],
sort: params[:sort])
@business_data = result.bunsiness_result
end
end
class DoComplexCommand
include GL::Command
def call
context.business_result = BusinessObject.method_call(offset: context.page * 50,
ordering_by: context.sort)
end
end
Failure and success
Should the business logic not be successful, a Context
can be failed via context.fail!
.
The context comes with an errors
of type ActiveModel::Errors
.
class SomeController
def index
result = DoComplexCommand.call(page: params[:page],
sort: params[:sort])
@business_data = result.bunsiness_result
render and return if result.success?
render_failure if result.failure?
end
end
class DoComplexCommand
include GL::Command
def call
context.business_result = BusinessObject.method_call(offset: context.page * 50,
ordering_by: context.sort)
if business_result.blank?
context.errors.add(:base, 'no data found.')
context.fail!
end
end
end
Should an exception occur, the interactor fails automatically and adds exception details to context.errors
.
class DoComplexCommand
include GL::Command
def call
raise StandardError
end
end
Rollback
Whenever a GL::Command fails, it executes rollback
if defined.
class DoComplexCommand
include GL::Command
def call
# change a lot of things
raise StandardError
end
def rollback
# undo all the changes
end
end
Hooks
GL::Commands offer before
, around
, and after
hooks.
class DoComplexCommand
include GL::Command
before :initialize_logger
around :measure_time
after :close_transaction
def call
context.business_result = BusinessObject.method_call(offset: context.page * 50,
ordering_by: context.sort)
if business_result.blank?
context.errors.add(:base, 'no data found.')
context.fail!
end
end
private
def initialize_logger
# initialize logger
end
def measure_time
time = Time.now
call
duration = Time.now - time
end
def close_transaction
# closing transaction
end
end