# Light::Services [![Build Status](https://travis-ci.org/light-ruby/light-services.svg?branch=master)](https://travis-ci.org/light-ruby/light-services) [![Code Climate](https://codeclimate.com/github/light-ruby/light-services/badges/gpa.svg)](https://codeclimate.com/github/light-ruby/light-services) [![Test Coverage](https://codeclimate.com/github/light-ruby/light-services/badges/coverage.svg)](https://codeclimate.com/github/light-ruby/light-services/coverage) Implementation of Service Object Pattern for Ruby/Rails. Compatible with Rails 5.1 and 5.0, 4.2, 4.1, 4.0. Service Object Pattern – What is it? Check it here: - [Wikipedia](https://en.wikipedia.org/wiki/Service_layer_pattern) - [Essential RubyOnRails patterns — part 1: Service Objects](https://medium.com/selleo/essential-rubyonrails-patterns-part-1-service-objects-1af9f9573ca1) ## Installation Add this line to your application's Gemfile: ```ruby gem 'light-services', '~> 0.5' ``` And then execute: $ bundle Or install it yourself as: $ gem install light-service ## Usage #### Examples of usage: **Change state of the record:** ```ruby class Painting::Publish < ApplicationService # Parameters param :painting, type: Painting param :user, type: User # Callbacks before :authorize after :send_email_notification def run painting.publish! end private def authorize pundit_authorize!(painting, user, :publish?) end def send_email_notification PaintingMailer.publish_email(painting).deliver_now end end ``` **Create a new record:** ```ruby class Owner::Create < ApplicationService # Parameters param :params, type: ActionController::Parameters param :user, type: User # Outputs output :owner # Callbacks before :assign_attributes before :authorize before :validate def run owner.save! end private def assign_attributes self.owner = Owner.new(owner_params) end def authorize pundit_authorize!(owner, user, :create?) end def validate return if owner.valid? errors.from_record(owner) end def owner_params params .require(:owner) .permit(:name) end end ``` **Integration with Pundit:** ```ruby class ApplicationService < Light::Services::Base def pundit_authorize!(record, user, action = nil) action = convert_action(action, :show?) policy = Pundit.policy!(user, record) return true if policy.public_send(action) Rails.logger.info "Pundit: not allowed to #{action} this #{record.inspect}" raise Pundit::NotAuthorizedError, query: action, policy: policy, record: record end def pundit_scope!(scope, user, action = nil) action = convert_action(action, :index?) pundit_authorize!(scope, user, action) Pundit.policy_scope!(user, scope) end private def convert_action(action, default) action = action.to_s return default if action.blank? return action if action.ends_with?('?') action + '?' end end ``` ## 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](https://rubygems.org). ## Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/light-service. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. ## License The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).