Generalize to pass an options hash to decorators

This commit is contained in:
Jeff Felchner 2011-11-09 19:02:23 -06:00
parent 78b200a84f
commit 03910877d0
4 changed files with 47 additions and 47 deletions

View File

@ -15,15 +15,15 @@ module Draper
# 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
@ -31,8 +31,8 @@ module Draper
#
# @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
@ -43,7 +43,7 @@ module Draper
# 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`
@ -83,7 +83,7 @@ module Draper
# 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
@ -91,31 +91,31 @@ module Draper
# 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)
end
# Fetch all instances of the decorated class and decorate them.
#
# @param [Object] context (optional)
# @return [Draper::DecoratedEnumerableProxy]
def self.all(context = {})
Draper::DecoratedEnumerableProxy.new(model_class.all, self, context)
end
def self.first(context = {})
decorate(model_class.first, context)
# @param [Hash] options (optional)
def self.decorate(input, options = {})
input.respond_to?(:each) ? Draper::DecoratedEnumerableProxy.new(input, self, options) : new(input, options)
end
def self.last(context = {})
decorate(model_class.last, context)
# Fetch all instances of the decorated class and decorate them.
#
# @param [Hash] options (optional)
# @return [Draper::DecoratedEnumerableProxy]
def self.all(options = {})
Draper::DecoratedEnumerableProxy.new(model_class.all, self, options)
end
def self.first(options = {})
decorate(model_class.first, options)
end
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
@ -124,13 +124,13 @@ module Draper
# 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.
#
@ -141,7 +141,7 @@ module Draper
# 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
@ -165,11 +165,11 @@ module Draper
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
@ -177,6 +177,6 @@ module Draper
private
def allow?(method)
(!allowed? || allowed.include?(method) || FORCED_PROXY.include?(method)) && !denied.include?(method)
end
end
end
end

View File

@ -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)

View File

@ -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

View File

@ -135,7 +135,7 @@ describe Draper::Base do
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
@ -164,7 +164,7 @@ describe Draper::Base do
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] }
@ -189,7 +189,7 @@ describe Draper::Base do
subject.should == other
end
end
context 'position accessors' do
[:first, :last].each do |method|
context "##{method}" do
@ -202,9 +202,9 @@ describe Draper::Base do
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
@ -273,9 +273,9 @@ describe Draper::Base do
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