Skip to content

Instantly share code, notes, and snippets.

@bsodmike
Created October 24, 2012 19:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bsodmike/3948161 to your computer and use it in GitHub Desktop.
Save bsodmike/3948161 to your computer and use it in GitHub Desktop.
Decorator and Presenter Patterns in Rails 3.2.X
require 'delegate'
class Decorator < BasicObject
undef_method :==
def initialize(component)
@component = component
end
def method_missing(name, *args, &block)
@component.send(name, *args, &block)
end
end
class ListingDecorator < Decorator
# reader to access decorated object
def listing
@component
end
def at_state?(state)
listing.state == state.to_s
end
# Initialize a new decorator instance by passing in
# an instance of the source class.
#
# When passing in a single object, using `.decorate` is
# identical to calling `.new`.
def self.decorate(component)
new(component)
end
end
class ListingPresenter
def initialize(component)
@component = component
end
def listing
@component
end
def progress_at(state)
# ...
end
end
@bsodmike
Copy link
Author

Alternative decorator based on SimpleDelegator

require 'delegate'

class Decorator < SimpleDelegator
  def class
    __getobj__.class
  end
end

Transparency in action

[4] pry(main)> ListingDecorator.decorate(listing).at_state?('step_final')
=> true
[35] pry(main)> dec = ListingDecorator.decorate(listing)
=> #<Listing id: 3
[36] pry(main)> ListingDecorator.decorate(listing).methods.size
=> 1037
[40] pry(main)> dec.foo
NoMethodError: undefined method `foo' for #<Listing:0x007fca704ac558>

Ref: http://robots.thoughtbot.com/post/14825364877/evaluating-alternative-decorator-implementations-in

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