Skip to content

Instantly share code, notes, and snippets.

@nicholasjhenry
Created October 12, 2012 17:28
Show Gist options
  • Select an option

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

Select an option

Save nicholasjhenry/3880386 to your computer and use it in GitHub Desktop.
An example of using Ruby Events Gem
# Example:
#
# submit_order = SubmitOrder.new(current_user, order)
# submit_order.call
#
# Uses RubyEvents: https://github.com/nathankleyn/ruby_events
# app/use_cases/submit_order.rb
class SubmitOrder
CannotAuthorizePayment = Class.new(StandardError)
attr_reader :customer, :order
def initialize(customer, order)
@order, @customer = order, customer
end
def call
order.events.listen(:submitted) do |order|
payment_processor.authorize(order, card_on_file)
cart.empty!
end
payment_processor.listen(:authorization_succeeded) do |transaction|
order.paid!(card_on_file, transaction)
end
payment_processor.listen(:authorization_failed) do |transaction|
raise CannotAuthorizePayment.new
end
order.events.listen(:paid) do |order|
order.prepare_shipment!
end
order.events.listen(:shipment_prepared) do |order|
inventory.update!(order.variants)
send_notifications
end
order.submit!
end
private
def send_notifications
BuyerMailer.delay(:queue => 'email', :priority => 30).order_confirmation(order.id)
end
def cart
Cart.new(order)
end
def payment_processor
PaymentProcessor.new
end
def inventory
Inventory.new
end
def card_on_file
customer.card_on_file
end
end
# app/models/order.rb
class Order < ActiveRecord::Base
# associations defined here
def submit!(listeners)
self.class.transaction do
events.fire(:submitted, self)
save!
end
end
def paid!(credit_card, transaction)
order.credit_card = credit_card
order_purchased!
payout_pending!
create_payment(transaction_id: transaction.id)
events.fire(:paid, self)
end
def prepare_shipment!
create_shipment
events.fire(:shipment_prepared, self)
end
private
def add_shipment
Shipment.build(order: self)
end
def add_payment(attributes)
Payment.new(attributes.merge(order: self))
end
end
# app/models/cart.rb
class Cart
attr_reader :order
def initialize(order)
@order = order
end
def empty!
order.cart_items.destroy_all
end
end
# app/models/payment_processor.rb
class PaymentProcessor
def authorize(order)
result = PaymentGateway.authorize(credit_card, order)
if result.success?
events.fire(:authorization_succeeded, result.transaction)
else
events.fire(:authorization_failed, result.transaction)
end
end
end
# app/models/inventory.rb
class Inventory
def update!(variants)
variants.each { |item| item.decrement_count_on_hand }
end
end
# app/models/shipment.rb
class Shipment < ActiveRecord::Base
def self.build(order)
shipment_factory = ShipmentFactory.new(self)
shipment_factory.build(order)
end
end
# app/models/shipment_factory.rb
class ShipmentFactory < SimpleDelegator
def build(order)
case
when order.for_managed_account?
build_managed_for(order)
when order.has_sure_shop?
build_managed_for(order)
build_addressed_to_shophers_for(order)
else
build_unmanaged_for(order)
end
events.fire(:prepared, self)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment