Skip to content

Instantly share code, notes, and snippets.

@bsodmike
Created February 26, 2015 13:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bsodmike/b878b2a2b160d4056209 to your computer and use it in GitHub Desktop.
Save bsodmike/b878b2a2b160d4056209 to your computer and use it in GitHub Desktop.
Simple Decorator Using Ruby Delegate for Ruby 2.1.5 & Rails 4
module Project
module Decorators
module Draperize
def self.included _klass
_klass.class_eval { extend ClassMethods }
end
module ClassMethods
# Initialize a new decorator instance by passing in
# an instance of class `_klass`.
#
# When passing in a single object, using `.decorate` is
# identical to calling `.new`.
def decorate(component)
new(component)
end
end
end
require 'delegate'
class Base < SimpleDelegator
def initialize(component)
super
@component = component
end
def class
__getobj__.class
end
end
class ProductDecorator < Base
include Draperize
# Add methods to decorate `component`
def decorated?
"Why, yes! Here's your decorated product '#{name}' (#{@component})"
end
end
end
end
class Product
def initialize
@name = "SPAM!"
end
attr_reader :name
end
p = Product.new
dp = Project::Decorators::ProductDecorator.decorate(p)
puts "p methods: #{p.methods.count}\n"
puts "dp methods: #{dp.methods.count}\n"
extra_methods = ((p.methods | dp.methods) - (p.methods & dp.methods))
puts "Decorated methods in dp: #{extra_methods.inspect}\n"
puts "Calling dp#decorated?: #{dp.decorated?}\n"
puts "dp class: #{dp.class}\n"
@bsodmike
Copy link
Author

foo@localhost [18:53:24] code/ruby {2.1.5}
-> % ruby decorator.rb
p methods: 56
dp methods: 62
Decorated methods in dp: [:decorated?, :__getobj__, :__setobj__, :method_missing, :marshal_dump, :marshal_load]
Calling dp#decorated?: Why, yes! Here's your decorated product 'SPAM!' (#<Product:0x007fd29909f650>)
dp class: Product

References

  1. https://robots.thoughtbot.com/evaluating-alternative-decorator-implementations-in
  2. http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
  3. https://blog.engineyard.com/2014/keeping-your-rails-controllers-dry-with-services

Thanks

To David (@workmad3) for spotting an obvious blunder on my part!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment