Skip to content

Instantly share code, notes, and snippets.

@nicholasjhenry
Last active December 24, 2015 09:58
Show Gist options
  • Select an option

  • Save nicholasjhenry/6780432 to your computer and use it in GitHub Desktop.

Select an option

Save nicholasjhenry/6780432 to your computer and use it in GitHub Desktop.
Alternative implementation to LightService example https://github.com/adomokos/light-service
class TaxController < ApplicationController
def update
update_tax.call(order)
redirect_to checkout_shipping_path(order), :notice => "Tax was calculated successfully"
rescue BusinessException => e
render :action => :edit, :error => e.message
end
private
def update_tax
UpdateTaxFactory.build
end
def order
@order ||= Order.find(params[:id])
end
end
class UpdateTaxFactory
def self.build
UpdateTax.new(tax_calculator) do |service|
service.add_listener FreeShippingListener.new
end
end
private
def self.tax_calculator
TaxCalculator.new
end
end
class TaxCalculator
def initialize
@tax_ranges = TaxRange
end
def calculate(order)
tax_ranges = @tax_ranges.for_region(order.region)
raise BusinessException.new("The tax ranges were not found") if tax_ranges.nil?
tax_percentage = tax_ranges.for_total(order.total)
raise BusinessException.new("The tax percentage was not found") if tax_percentage.nil?
order.total * (tax_percentage/100).round(2)
end
end
class UpdateTax
include Annoucer
def initialize(tax_calculator)
@tax_calculator = tax_calculator
yield self if block_given?
end
def call(order)
tax_total = @tax_calculator.calculate(order)
order.update_attribute(:tax, tax_total)
annouce :tax_updated, order
end
end
class FreeShippingListener
def tax_updated(order)
assign_free_shipping(order)
end
private
def assign_free_shipping(order)
unless FreeShippingPolicy.applicable?(order)
order.provide_free_shipping!
end
end
class FreeShippingPolicy
def self.applicable?(order)
order.total_with_tax > 200
end
end
# Framework code
#
require 'set'
module Announcer
def announce(event, *args)
listeners.each { listener.send(event, *args) if listener.respond_to?(event) }
end
def add_listener(listener)
listeners.add(listener)
end
def listeners
@listeners ||= Set.new
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment