Skip to content

Commit

Permalink
Generalize to pass an options hash to decorators
Browse files Browse the repository at this point in the history
  • Loading branch information
jfelchner committed Nov 10, 2011
1 parent 78b200a commit 0391087
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 42 deletions.
54 changes: 27 additions & 27 deletions lib/draper/base.rb
Expand Up @@ -15,24 +15,24 @@ class Base

# Initialize a new decorator instance by passing in
# an instance of the source class. Pass in an optional
# context is stored for later use.
# context inside the options hash is stored for later use.
#
# @param [Object] instance to wrap
# @param [Object] context (optional)
def initialize(input, context = {})
# @param [Hash] options (optional)
def initialize(input, options = {})
input.inspect # forces evaluation of a lazy query from AR
self.class.model_class = input.class if model_class.nil?
@model = input
self.context = context
self.context = options.fetch(:context, {})
end

# Proxies to the class specified by `decorates` to automatically
# lookup an object in the database and decorate it.
#
# @param [Symbol or String] id to lookup
# @return [Object] instance of this decorator class
def self.find(input, context = {})
self.new(model_class.find(input), context)
def self.find(input, options = {})
self.new(model_class.find(input), options)
end

# Typically called within a decorator definition, this method
Expand All @@ -43,7 +43,7 @@ def self.find(input, context = {})
# But they don't have to match in name, so a `EmployeeDecorator`
# class could call `decorates :person` to wrap instances of `Person`
#
# This is primarilly set so the `.find` method knows which class
# This is primarilly set so the `.find` method knows which class
# to query.
#
# @param [Symbol] class_name snakecase name of the decorated class, like `:product`
Expand Down Expand Up @@ -83,39 +83,39 @@ def self.allows(*input_allows)

# Initialize a new decorator instance by passing in
# an instance of the source class. Pass in an optional
# context is stored for later use.
# context into the options hash is stored for later use.
#
# When passing in a single object, using `.decorate` is
# identical to calling `.new`. However, `.decorate` can
# also accept a collection and return a collection of
# individually decorated objects.
#
# @param [Object] instance(s) to wrap
# @param [Object] context (optional)
def self.decorate(input, context = {})
input.respond_to?(:each) ? Draper::DecoratedEnumerableProxy.new(input, self, context) : new(input, context)
# @param [Hash] options (optional)
def self.decorate(input, options = {})
input.respond_to?(:each) ? Draper::DecoratedEnumerableProxy.new(input, self, options) : new(input, options)
end

# Fetch all instances of the decorated class and decorate them.
#
# @param [Object] context (optional)
# @param [Hash] options (optional)
# @return [Draper::DecoratedEnumerableProxy]
def self.all(context = {})
Draper::DecoratedEnumerableProxy.new(model_class.all, self, context)
def self.all(options = {})
Draper::DecoratedEnumerableProxy.new(model_class.all, self, options)
end
def self.first(context = {})
decorate(model_class.first, context)

def self.first(options = {})
decorate(model_class.first, options)
end

def self.last(context = {})
decorate(model_class.last, context)
def self.last(options = {})
decorate(model_class.last, options)
end

# Access the helpers proxy to call built-in and user-defined
# Rails helpers. Aliased to `.h` for convinience.
#
# @return [Object] proxy
# @return [Object] proxy
def helpers
self.class.helpers
end
Expand All @@ -124,13 +124,13 @@ def helpers
# Access the helpers proxy to call built-in and user-defined
# Rails helpers from a class context.
#
# @return [Object] proxy
# @return [Object] proxy
class << self
def helpers
Draper::ViewContext.current
end
alias :h :helpers
end
end

# Fetch the original wrapped model.
#
Expand All @@ -141,7 +141,7 @@ def to_model

# Delegates == to the decorated models
#
# @return [Boolean] true if other's model == self's model
# @return [Boolean] true if other's model == self's model
def ==(other)
@model == (other.respond_to?(:model) ? other.model : other)
end
Expand All @@ -165,18 +165,18 @@ def method_missing(method, *args, &block)
super
end
end

def self.method_missing(method, *args, &block)
model_class.send(method, *args, &block)
end

def self.respond_to?(method, include_private = false)
super || model_class.respond_to?(method)
end

private
def allow?(method)
(!allowed? || allowed.include?(method) || FORCED_PROXY.include?(method)) && !denied.include?(method)
end
end
end
end
8 changes: 4 additions & 4 deletions lib/draper/decorated_enumerable_proxy.rb
Expand Up @@ -2,16 +2,16 @@ module Draper
class DecoratedEnumerableProxy
include Enumerable

def initialize(collection, klass, context)
@wrapped_collection, @klass, @context = collection, klass, context
def initialize(collection, klass, options = {})
@wrapped_collection, @klass, @options = collection, klass, options
end

def each(&block)
@wrapped_collection.each { |member| block.call(@klass.new(member, @context)) }
@wrapped_collection.each { |member| block.call(@klass.new(member, @options)) }
end

def to_ary
@wrapped_collection.map { |member| @klass.new(member, @context) }
@wrapped_collection.map { |member| @klass.new(member, @options) }
end

def method_missing (method, *args, &block)
Expand Down
8 changes: 4 additions & 4 deletions lib/draper/model_support.rb
@@ -1,14 +1,14 @@
module Draper::ModelSupport
def decorator
@decorator ||= "#{self.class.name}Decorator".constantize.decorate(self)
def decorator(options = {})
@decorator ||= "#{self.class.name}Decorator".constantize.decorate(self, options)
block_given? ? yield(@decorator) : @decorator
end

alias :decorate :decorator

module ClassMethods
def decorate(context = {})
@decorator_proxy ||= "#{model_name}Decorator".constantize.decorate(self.scoped)
def decorate(options = {})
@decorator_proxy ||= "#{model_name}Decorator".constantize.decorate(self.scoped, options)
block_given? ? yield(@decorator_proxy) : @decorator_proxy
end
end
Expand Down
14 changes: 7 additions & 7 deletions spec/draper/base_spec.rb
Expand Up @@ -135,7 +135,7 @@ class BusinessDecorator < Draper::Base
end

it "should accept and store a context" do
pd = ProductDecorator.find(1, :admin)
pd = ProductDecorator.find(1, :context => :admin)
pd.context.should == :admin
end
end
Expand Down Expand Up @@ -164,7 +164,7 @@ class BusinessDecorator < Draper::Base
context "with a context" do
let(:context) {{ :some => 'data' }}

subject { Draper::Base.decorate(source, context) }
subject { Draper::Base.decorate(source, :context => context) }

context "when given a collection of source objects" do
let(:source) { [Product.new, Product.new] }
Expand All @@ -189,7 +189,7 @@ class BusinessDecorator < Draper::Base
subject.should == other
end
end

context 'position accessors' do
[:first, :last].each do |method|
context "##{method}" do
Expand All @@ -202,9 +202,9 @@ class BusinessDecorator < Draper::Base
end

it "should accept an optional context" do
ProductDecorator.send(method, :admin).context.should == :admin
ProductDecorator.send(method, :context => :admin).context.should == :admin
end
end
end
end
end

Expand Down Expand Up @@ -273,9 +273,9 @@ module Paginator; def page_number; "magic_value"; end; end
it "should return a decorated collection" do
ProductDecorator.all.first.should be_instance_of ProductDecorator
end

it "should accept a context" do
collection = ProductDecorator.all(:admin)
collection = ProductDecorator.all(:context => :admin)
collection.first.context.should == :admin
end
end
Expand Down

0 comments on commit 0391087

Please sign in to comment.