Skip to content

PORO Domain Objects

cavalle edited this page Jan 7, 2013 · 2 revisions

Version #1

http://solnic.eu/2011/08/01/making-activerecord-models-thin.html

class User < ActiveRecord::Base
  validates :email, :name, :presence => true
end
 
class Product < ActiveRecord::Base
  validates :name, :sold, :presence => true
end
 
class Order < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
end
class Shop
  class Warehouse
    def self.find(id)
      Product.find_by_id(id)
    end
  end
 
  class Customer
    attr_reader :user
 
    def self.find(id)
      User.find_by_id(id)
    end
 
    def initialize(user)
      @user = user
    end
 
    def pay(product)
      # perform the payment
    end
  end
 
  class Transaction
    attr_reader :customer, :product, :order, :status
 
    def initialize(customer, product)
      @customer = customer
      @product  = product
    end
 
    def commit
      @status = customer.pay(product)
 
      if success?
        commit!
      end
    end
 
    def commit!
      create_order
 
      if order.persisted?
        mark_product_as_sold
      end
    end
 
    def success?
      status === true
    end
 
    private
 
    def create_order
      @order = Order.create(:user =&gt; customer, :product =&gt; product)
    end
 
    def mark_product_as_sold
      @product.update_attribute(:sold, true)
    end
  end
end
customer    = Shop::Customer.find(customer_id)
product     = Shop::Warehouse.find(product_id)
transaction = Shop::Transaction.new(customer, product)
 
transaction.commit

Version #2

class OrdersController < ActionController::Base
  def close
    #retrieval
    payment_handler = Payment.for(params[:method], params[:card])
    process = OrderProcess.new(order, payment_handler)
    process.close
    #rendering
  end
end
class Payment
  def self.for(method, card_details=nil)
    if method == "card"
      CardPayment.new(card_details)
    else
      new
    end
  end

  def handle_payment
    #default payment handling code
  end
end
class CardPayment
  #...

  def handle_payment
    ExternalPaymentService.new.charge(@card_details)
  end
end
class OrderProcess
  #...

  def close
    @payment_handler.handle_payment
    Delivery.create! :status => :pending, :order => @order
    @order.close!
  end
end
class Order < ActiveRecord::Base
  #...

  def close!
    self.closed = true
    self.save!
  end
end

Clone this wiki locally