Move :infer option to CollectionDecorator

This commit is contained in:
Andrew Haines 2012-11-07 21:35:02 +00:00
parent ea91db9850
commit 30104b0fc0
4 changed files with 21 additions and 26 deletions

View File

@ -11,7 +11,8 @@ module Draper
# @param source collection to decorate
# @param options [Hash] passed to each item's decorator (except
# for the keys listed below)
# @option options [Class] :with the class used to decorate items
# @option options [Class,Symbol] :with the class used to decorate
# items, or `:infer` to call each item's `decorate` method instead
def initialize(source, options = {})
@source = source
@decorator_class = options.delete(:with) || self.class.inferred_decorator_class
@ -23,7 +24,7 @@ module Draper
end
def decorated_collection
@decorated_collection ||= source.collect {|item| decorator_class.decorate(item, options) }
@decorated_collection ||= source.collect {|item| decorate_item(item) }
end
def find(*args, &block)
@ -61,6 +62,14 @@ module Draper
protected
def decorate_item(item)
if decorator_class == :infer
item.decorate(options)
else
decorator_class.decorate(item, options)
end
end
def self.inferred_decorator_class
decorator_name = "#{name.chomp("Decorator").singularize}Decorator"
decorator_uninferrable if decorator_name == name

View File

@ -2,7 +2,7 @@ module Draper::Decoratable
extend ActiveSupport::Concern
def decorator(options = {})
@decorator ||= decorator_class.decorate(self, options.merge(:infer => false))
@decorator ||= decorator_class.decorate(self)
block_given? ? yield(@decorator) : @decorator
end
alias_method :decorate, :decorator

View File

@ -124,17 +124,13 @@ module Draper
# individually decorated objects.
#
# @param [Object] input instance(s) to wrap
# @param [Hash] options (optional)
# @option options [Boolean] :infer If true, each model will be
# wrapped by its inferred decorator.
# @param [Hash] options options to be passed to the decorator
def self.decorate(input, options = {})
if input.instance_of?(self)
input.options = options unless options.empty?
return input
elsif input.respond_to?(:each) && !input.is_a?(Struct) && (!defined?(Sequel) || !input.is_a?(Sequel::Model))
Draper::CollectionDecorator.new(input, options.merge(with: self))
elsif options[:infer]
input.decorator(options)
Draper::CollectionDecorator.new(input, options.reverse_merge(with: self))
else
new(input, options)
end

View File

@ -30,7 +30,7 @@ describe Draper::Decorator do
end
end
context ".decorate" do
describe ".decorate" do
context "without any context" do
subject { Draper::Decorator.decorate(source) }
@ -127,8 +127,8 @@ describe Draper::Decorator do
let(:source) { [Product.new, Widget.new] }
it "returns a collection of wrapped objects all with the same decorator" do
subject.first.class.should be Draper::Decorator
subject.last.class.should be Draper::Decorator
subject.first.should be_an_instance_of Draper::Decorator
subject.last.should be_an_instance_of Draper::Decorator
end
end
@ -138,28 +138,18 @@ describe Draper::Decorator do
let(:source) { Product.new }
it "returns a decorator of the type explicity used in the call" do
subject.class.should be Draper::Decorator
subject.should be_an_instance_of Draper::Decorator
end
end
context "returns a collection containing only the explicit decorator used in the call" do
subject { Draper::Decorator.decorate(source, infer: true).to_ary }
subject { Draper::Decorator.decorate(source, with: :infer) }
let(:source) { [Product.new, Widget.new] }
it "returns a mixed collection of wrapped objects" do
subject.first.class.should be ProductDecorator
subject.last.class.should be WidgetDecorator
end
end
context "when given a single object" do
subject { Draper::Decorator.decorate(source, infer: true) }
let(:source) { Product.new }
it "can also infer its decorator" do
subject.class.should be ProductDecorator
subject.first.should be_an_instance_of ProductDecorator
subject.last.should be_an_instance_of WidgetDecorator
end
end
end