Skip to content

Provides an interface for creating single purpose objects

License

Notifications You must be signed in to change notification settings

erickbrower/responsibility

Repository files navigation

Responsibility Build Status Gem Version

A Responsibility is a class that provides a single piece of functionality, as per the Single Responsibility Principle. This class provides a single method called "perform", with optional "before" and "after" hooks. It also keeps track of any errors set during execution.

Installation

Add this line to your application's Gemfile:

gem 'responsibility'

And then execute:

$ bundle

Or install it yourself as:

$ gem install responsibility

Usage

Define a class, include Responsibility, and define a perform method. If before is defined and returns false or calls fail! then the perform or after methods will not be run. The same rule applies to perform, and in the case of failure after will not be called.

Any keyword arguments (or just a hash) passed to perform will become attributes of the resulting object

A simple example could be something like:

class UserSignupService
  include Responsibility

  def before
    unless user.present? && user.valid?
      errors << "User was not provided or is not valid"
    end
  end

  def perform
    user.save
  end

  def after
    UserConfirmationEmailService.perform(email: user.email)
  end
end

user = User.new(
  email: "cerickbrower@gmail.com",
  password: "Wubba Lubba Dub Dub!"
)
result = UserSignupService.perform(user: user)
result.success? #=> true
result.errors #=> []
result.user #=> Our newly persisted user

If errors are created during before, perform, or after then the service fails. In the example above, if the user isn't valid we add an error. In this case the result object would look like:

user = User.new(
  email: "",
  password: ""
)
result = UserSignupService.perform(user: user)
result.success? #=> false
result.errors #=> ["User was not provided or is not valid"]

Another contrived example with an explicit failure, assuming the User object couldn't be persisted:

class UserSignupService
  include Responsibility

  def before
    unless user.present? && user.valid?
      errors << "User was not provided or is not valid"
    end
  end

  def perform
    unless user.save
      fail!(message: "User could not be saved")
    end
  end

  def after
    UserConfirmationEmailService.perform(email: user.email)
  end
end

result = UserSignupService.perform(user: user)
result.success?  #=> false
result.errors #=> ["User could not be saved"]

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/erickbrower/responsibility.

About

Provides an interface for creating single purpose objects

Resources

License

Stars

Watchers

Forks

Packages

No packages published