Allow decorators to be inferred (Take 3)

This commit is contained in:
Jeff Felchner 2011-11-09 21:31:48 -06:00
parent 03910877d0
commit 404f9d9044
8 changed files with 60 additions and 5 deletions

View File

@ -93,7 +93,13 @@ module Draper
# @param [Object] instance(s) to wrap
# @param [Hash] options (optional)
def self.decorate(input, options = {})
input.respond_to?(:each) ? Draper::DecoratedEnumerableProxy.new(input, self, options) : new(input, options)
if input.respond_to?(:each)
Draper::DecoratedEnumerableProxy.new(input, self, options)
elsif options[:infer]
input.decorator(options)
else
new(input, options)
end
end
# Fetch all instances of the decorated class and decorate them.

View File

@ -7,11 +7,11 @@ module Draper
end
def each(&block)
@wrapped_collection.each { |member| block.call(@klass.new(member, @options)) }
@wrapped_collection.each { |member| block.call(@klass.decorate(member, @options)) }
end
def to_ary
@wrapped_collection.map { |member| @klass.new(member, @options) }
@wrapped_collection.map { |member| @klass.decorate(member, @options) }
end
def method_missing (method, *args, &block)

View File

@ -1,9 +1,9 @@
module Draper::ModelSupport
def decorator(options = {})
@decorator ||= "#{self.class.name}Decorator".constantize.decorate(self, options)
@decorator ||= "#{self.class.name}Decorator".constantize.decorate(self, options.merge(:infer => false))
block_given? ? yield(@decorator) : @decorator
end
alias :decorate :decorator
module ClassMethods

View File

@ -181,6 +181,47 @@ describe Draper::Base do
end
end
context "does not infer collections by default" do
subject { Draper::Base.decorate(source).to_ary }
let(:source) { [Product.new, Widget.new] }
it "returns a collection of wrapped objects all with the same decorator" do
subject.first.class.name.should eql 'Draper::Base'
subject.last.class.name.should eql 'Draper::Base'
end
end
context "does not infer single items by default" do
subject { Draper::Base.decorate(source) }
let(:source) { Product.new }
it "returns a decorator of the type explicity used in the call" do
subject.class.should eql Draper::Base
end
end
context "returns a collection containing only the explicit decorator used in the call" do
subject { Draper::Base.decorate(source, :infer => true).to_ary }
let(:source) { [Product.new, Widget.new] }
it "returns a mixed collection of wrapped objects" do
subject.first.class.should eql ProductDecorator
subject.last.class.should eql WidgetDecorator
end
end
context "when given a single object" do
subject { Draper::Base.decorate(source, :infer => true) }
let(:source) { Product.new }
it "can also infer its decorator" do
subject.class.should eql ProductDecorator
end
end
end
context('.==') do

2
spec/samples/widget.rb Normal file
View File

@ -0,0 +1,2 @@
class Widget < Product
end

View File

@ -0,0 +1,2 @@
class WidgetDecorator < ProductDecorator
end

View File

@ -0,0 +1,2 @@
class Widget < Product
end

View File

@ -0,0 +1,2 @@
class WidgetDecorator < ProductDecorator
end