Project

procedure

0.01
No commit activity in last 3 years
No release in over 3 years
Mariage of policy object and interactor patterns
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0
~> 3.7, >= 3.7.0
 Project Readme

Procedure

When you check multiple conditions, allow for some action only when all requirements are met and need feedback which conditions were not met in the opposite case, the procedure gem is for you.

Examples:

Installation

Add the gem to your Gemfile:

bundle add procedure

Usage

Let's assume that we have the following user:

User = Struct.new(:first_name, :country, :age, keyword_init: true)
user = User.new(
  first_name: 'John',
  country: 'USA',
  age: 20
)

We would allow him to enter the system only if he satisfies the following requirements:

  • first_name is present
  • age is greater than 25
  • country is Finland

If one of the requirements is not met, we would like to know about it. So we want to build the procedure with three steps:

# Verify first name
class VerifyFirstName
  include Procedure::Step

  def passed?
    !context.user.first_name.nil?
  end

  def failure_message
    'First name is blank'
  end
end

# Verify age
class VerifyAge
  include Procedure::Step

  def passed?
    context.user.age > 25
  end

  def failure_message
    'The user is not old enough'
  end
end

# Verify country
class VerifyCountry
  include Procedure::Step

  def passed?
    context.user.country == 'Finland'
  end

  def failure_message
    'The user is not from Finland'
  end
end

The last thing we need to do is to create an organizer, class that will perform the procedure with the all the steps we defined:

class UserProcedure
  include Procedure::Organizer

  steps VerifyFirstName, VerifyAge, VerifyCountry
end

We can now test the procedure:

outcome = UserProcedure.call(context: { user: user })
outcome.success? # => false
outcome.failure_messages # => ["The user is not old enough"]

By the default, the procedure would stop when one of the steps would not pass the verification. If you would like to continue the procedure to get the full feedback, you have to pass the fail_fast option explicitly:

outcome = UserProcedure.call(context: { user: user }, options: { fail_fast: false })
outcome.success? # => false
outcome.failure_messages # => ["The user is not old enough", "The user is not from Finland"]