= Hexx {Gem Version}[https://rubygems.org/gems/hexx] {Bild Status}[https://travis-ci.org/nepalez/hexx] {Code Metrics}[https://codeclimate.com/github/nepalez/hexx] {Dependency Status}[https://gemnasium.com/nepalez/hexx] {Coverage Status}[https://coveralls.io/r/nepalez/hexx] {License}[https://github.com/nepalez/hexx/blob/master/LICENSE.rdoc] The module provides a base service objects class and some features for the domain models (entities). Provides: * +Service+ base class for decoupling a domain business logics from a controller * +Models+ module for extending domain models. The module is expected to be used in PORO domain. For usage in active record domains consider { hexx-active_record }[https://github.com/nepalez/hexx-active_record] gem instead. == Installation Add this line to your application's Gemfile: gem "hexx", "~> 2.0" And then execute: $ bundle Or install it yourself as: $ gem install hexx == Pattern Service objects decouple business logics from: * Domain _models_ (entities). * Delivery mechanism _controllers_ (such as Rails framework). To follow object oriented architecture Hexx services exploit the *Observer* (Listener) pattern via { Wisper }[https://github.com/krisleech/wisper] gem. Some examples of this pattern implementation are available at the { wisper gem wiki }[https://github.com/krisleech/wisper/wiki]. === Service A typical service object is shown below: require 'hexx' class AddItem < Hexx::Service # whitelists parameters and defines corresponding attributes. allow_params :name # defines some validation using ActiveModel::Validations helpers. validate :name, presence: true # runs a service def run # re-raises StandardErrors as Hexx::Service::Invalid escape { MyModel.save! } rescue => err # Hexx::Service::Invalid only publish :error, err.messages else publish :success end end Usage of the service (in a Rails controller): class ItemsController < ActionController::Base # Creates an item with given name def create service = AddItem.new params.allow(:name) service.subscribe self, prefix: :on service.run end # Publishes a success message def on_created(item, messages) @item, @messages = item, messages render "created", status: 201 end # Publishes an error messages def on_error(messages) @messages = messages render "error" end end The controller knows nothing about the action itself. It only needs to sort out a request and send it to a corresponding service. Any controller action does one thing only. * +create+ action sorts out requests. * both +on_success+ and +on_created+ listens to services and report their results back to client. === Models and Entities The module also defines Hexx::Models module to extend domain models (entities). This allows coercion of attributes with +attr_coerced+ helper: class User extend Hexx::Models attr_coerced :name, type: ActiveSupport::Multibyte::Chars end user = User.new name: "Ivan" user.name # => "Ivan" user.name.class # => ActiveSupport::Multibyte::Chars The method redefines both getter and setter and can be used for value preparation: class StrippedString < String def initialize(value) super value.strip end end class User extend Hexx::Models attr_coerced :name, type: StrippedString end user = User.name " Ivan " user.name # => "Ivan" == Dependencies The module provides methods +depends_on+ and +config+ to create dependency injection framework. Declare gem dependencies (external classes and modules). # lib/my_gem.rb module MyGem extend Hexx::Dependencies depends_on :get_item, :add_item end Inject gem dependencies: # config/my_gem.rb MyGem.configure do |config| config.get_item = AnotherGem::Services::Get # as a constant config.add_item = "AnotherGem::Services::Add" # as a name of a constant end Use them somewhere in a code: MyGem.get_item # => AnotherGem::Services::Get MyGem.add_item # => AnotherGem::Services::Add # the name is constantized == Relevant Links * Matt Wynne's talk {Hexagonal Rails}[http://www.confreaks.com/videos/977-goruco2012-hexagonal-rails] * { wisper }[http://www.github.com/krisleech/wisper] gem by Kris Leech. == License The project is distributed under the {MIT LICENSE}[LICENSE.rdoc].