Project

sebastian

0.0
No commit activity in last 3 years
No release in over 3 years
Your personal demon butler at your services.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.16
~> 0.11
~> 10.0
~> 3.0
~> 0.52.0

Runtime

< 6, >= 4
 Project Readme

Sebastian

Version circleci

Sebastian makes it easy for you to have service objects in Ruby. It gives you a place to put your business logic. It also helps you write safer code by validating that your inputs conform to your expectations.

Installation

Add this line to your Gemfile:

gem 'sebastian'

Or install it manually:

$ gem install sebastian

Usage

To define a service object, create a subclass of Sebastian::Base. Then you need to do two things:

  1. Define your attributes.
  2. Define your business logic. Do this by implementing the #execute method. Each attribute you defined will be available. If any of the attributes are invalid, #execute won't be run.

That covers the basics. Let's put it all together into a simple example that squares a number.

class CreatePayment < Sebastian::Base
  attribute :amount
  attribute :email

  validates :amount, numericality: { only_integer: true }

  private

  def execute
    'payment_created' if create_payment
    errors.add(:payment)
  end

  def create_payment
    Payment.create(customer: create_customer, amount: amount)
  end

  def create_customer
    Customer.create(email: email)
  end
end

Call .perform on your service to execute it. You must pass a single hash to .perform. It will return an instance of your service. By convention, we call this an result. You can use the #ok? method to ask the result if it's ok. If it's not ok, take a look at its errors with #errors. When #ok?, the value returned from #execute will be stored in #value.

result = CreatePayment.perform(email: 'ciel@phantomhive.com', amount: 500)
result.ok?
# => true
result.value
# => "payment_created"

result = CreatePayment.perform(amount: 500)
result.ok?
# => false
result.errors.messages
# => {:payment=>["is not a valid"]}
result.value!
# => Sebastian::InvalidResultError: Payment is not valid

You can also use .perform! to execute. It's like .perform but more dangerous. It doesn't return an result. If the result would be invalid, it will instead raise an error. But if the result would be valid, it simply returns the value.

CreatePayment.perform!(email: 'ciel@phantomhive.com', amount: 500)
# => "payment_created"
CreatePayment.perform!(amount: 500)
# => Sebastian::InvalidResultError: Payment is not valid

Validations

These validations aren't provided by Sebastian. They're from ActiveModel. You can also use any custom validations you wrote yourself in your services.

class ValidatePayment < Sebastian::Validation
  attributes :amount, :email

  validates :email, presence: true
  validates :amount, numericality: { only_integer: true }
end

This works the same as Sebastian::Base except that it is not needed to specify #execute.

result = ValidatePayment.perform(amount: '5,00')
result.ok?
# => false
result.errors.messages
# => {{:email=>["can't be blank"], :amount=>["is not a number"]}

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/paypronl/sebastian.

License

The gem is available as open source under the terms of the MIT License.