# Wrapper objects
# Implement original object's interface
# Delegate methods to the original object
class Burger
def cost
50
end
end
class BurgerWithCheese < Burger
def cost
60 # +10 for cheese
end
end
class LargeBurger < Burger
def cost
65 # +15 for large
end
end
class LargeBurgerWithCheese < Burger
def cost
75 # +15 (for large) + 10 (for cheese)
end
end
class JumboBurgerWithCheese < Burger
def cost
90 # +15 (2xlarge) + 10 (cheese)
end
end
module Cheese
def cost
super + 10
end
end
module Large
def cost
super + 15
end
end
burger = Burger.new
burger.extend(Cheese)
burger.extend(Large)
p burger.cost #=> 75
class JumboBurger < Burger
def cost
80 # + 30 (2xlarge)
end
end
burger = Burger.new
burger.extend(Large)
p burger.cost #=> 65
burger.extend(Large)
p burger.cost #=> 65
class LargeBurger
def initialize(burger)
@burger = burger
end
end
class LargeBurger
def cost
@burger.cost + 15
end
end
class BurgerWithCheese
def initialize(burger)
@burger = burger
end
end
class BurgerWithCheese
def cost
@burger.cost + 10
end
end
burger = Burger.new
large_burger = LargeBurger.new(burger)
jumbo_burger = LargeBurger.new(large_burger)
jumbo_cheese_burger = BurgerWithCheese.new(jumbo_burger)
class BurgerDecorator < SimpleDelegator
def initialize(burger)
@burger = buger
super(@burger)
end
end
class LargeBurger < BurgerDecorator
def cost
super + 15
end
end
class BurgerWithCheese < BurgerDecorator
def cost
super + 10
end
end
class BasePresenter < SimpleDelegator
def initialize(object, context)
@model, @context = object, context
super(@model)
end
end
class BasePresenter
def h # helper method
@context
end
end
class PostPresenter < BasePresenter
def author
h.link_to super, h.user_path(super)
end
end
class PostsController
def show
post = Post.find params[:id]
@post = PostPresenter.new(post)
end
end
module ApplicationHelper
def present(object)
klass = "#{object.class}Presenter".constantize
presenter = klass.new(object, self)
yield(presenter) if block_given?
presenter
end
end
- present(@post) do |post|
%h1= post.title
%p.author= post.author
Draper
gem install draper
class PostsController
def show
@post = Post.find(params[:id]).decorate
end
end
class PostsController
def index
@posts = Post.all.decorate
end
end