Class: Service::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/service/runner.rb

Overview

Service::Runner

This class is automatically used when passing a block to the ‘.call` method of a service. Its main purpose is to ease how actions can be run upon a service completion. Since a service will likely return the same kind of things over and over, this allows us to not have to repeat the same boilerplate code in every object.

There are several available actions and we can add new ones very easily:

  • on_success: will execute the provided block if the service succeeds

  • on_failure: will execute the provided block if the service fails

  • on_failed_step(name): will execute the provided block if the step named ‘name` fails

  • on_failed_policy(name): will execute the provided block if the policy named ‘name` fails

  • on_failed_contract(name): will execute the provided block if the contract named ‘name` fails

  • on_model_not_found(name): will execute the provided block if the model named ‘name` is not present

  • on_model_errors(name): will execute the provided block if the model named ‘name` contains validation errors

  • on_exceptions(*exceptions): will execute the provided block if any exceptions were caught by the ‘try` block. One or more exception classes can be provided to specifically handle those exceptions.

All the specialized steps receive the failing step result object as an argument to their block. ‘on_model_errors` receives the actual model so it’s easier to inspect it, and `on_exceptions` receives the actual exception.

The actions will be evaluated in the order they appear. So even if the service ultimately fails with a failed policy, in this example only the on_failed_policy action will be executed and not the on_failure one. The only exception to this being on_failure as it will always be executed last.

Examples:

In a controller

def create
  MyService.call do
    on_success do
      flash[:notice] = "Success!"
      redirect_to a_path
    end
    on_failed_policy(:a_named_policy) { |policy| redirect_to root_path, alert: policy.reason }
    on_failure { render :new }
  end
end

In a job

def execute(*)
  MyService.call(*) do
    on_success { Rails.logger.info "SUCCESS" }
    on_failure { Rails.logger.error "FAILURE" }
  end
end

Class Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method_name, *args, &block) ⇒ Object (private)



169
170
171
172
# File 'lib/service/runner.rb', line 169

def method_missing(method_name, *args, &block)
  return super unless AVAILABLE_ACTIONS[method_name]
  add_action(method_name, *args, &block)
end

Class Method Details

.call(service, dependencies = {}, &block) ⇒ void

This method returns an undefined value.

Parameters:

  • service (Class)

    a class including Base

  • dependencies (Hash) (defaults to: {})

    dependencies to be provided to the service

  • block (Proc)

    a block containing the steps to match on



125
126
127
# File 'lib/service/runner.rb', line 125

def self.call(service, dependencies = {}, &block)
  new(service, block.binding.eval("self"), dependencies).call(&block)
end