vadviktor
2/23/2014 - 5:44 AM

reuse.rb

## INHERIT from a base class
# -----------------------------------------

class Product < ActiveRecord::Base
  belongs_to :category

  def self.lookup(item_code)
    where(:item_code => item_code).first
  end
end

## INCLUDE a module into a class
# -----------------------------------------

class Order
  include Enumerable

  def initialize(products)
    @products = product
  end

  def each
    @products.each { |e| yield(e) }
  end

  def total_price
    reduce { |s,e| s + e.price }
  end
end

# EXTEND an individual object with a module
# -----------------------------------------

module Shopper
  def add_to_cart(product)
    cart << product
  end

  private

  def cart
    @cart ||= []
  end
end

# Usage:

current_user.extend(Shopper)
current_user.add_to_cart(product)

# PATCH a class definition
# -----------------------------------------

class Numeric
  BASE_CURRENCY = "USD"

  # NOTE: This is a terrible idea, don't actually do it!
  def in_currency(target)
     Currency.new(self, BASE_CURRENCY, target)
  end
end

# usage
p 10.in_currency("GBP") #=> 6.36

# EVAL some code in the context of another object
# -------------------------------------------------

FactoryGirl.define do
  factory :product do
    name          "Super crusher 5000"
    description   "The best product ever"
    price         500
  end
end

# ...

# build() returns a saved Product instance
product = FactoryGirl.build(:product) 

p product.price #=> 500


# DECORATE an object using a dynamic proxy
# -------------------------------------------------

require "delegate"

class InternationalProduct < DelegateClass(Product)
  BASE_CURRENCY = "USD"

  def initialize(product, currency)
    @product  = product
    @currency = currency

    super(@product)
  end
  
  def price
    Currency.convert(@product.price, @currency, BASE_CURRENCY)
  end
end


# Usage:

product = InternationalProduct.new(Product.find(1337), "GBP")

p product.description # delegates to Product
p product.price       # uses InternationalProduct's definition

## COMPOSE objects using simple aggregation techniques
# -------------------------------------------------

class SalesReport
  def initialize(products)
    @products = products
  end

  def summary
    "Your order:\n\n" +
    @products.map { |e| "* #{e.name}: #{e.price}" }.join("\n")
  end
end