diff --git a/lib/draper/collection_decorator.rb b/lib/draper/collection_decorator.rb index 2644c87..2b3b45f 100644 --- a/lib/draper/collection_decorator.rb +++ b/lib/draper/collection_decorator.rb @@ -41,7 +41,7 @@ module Draper "inferred decorators" end - "#" + "#<#{self.class.name} of #{klass} for #{source.inspect}>" end def context=(value) diff --git a/lib/draper/decorator.rb b/lib/draper/decorator.rb index 979b883..78bc839 100755 --- a/lib/draper/decorator.rb +++ b/lib/draper/decorator.rb @@ -141,7 +141,7 @@ module Draper # @option options [Hash] :context context available to decorated items def self.decorate_collection(source, options = {}) options.assert_valid_keys(:with, :context) - Draper::CollectionDecorator.new(source, options.reverse_merge(with: self)) + collection_decorator_class.new(source, options.reverse_merge(with: self)) end # Get the chain of decorators applied to the object. @@ -218,6 +218,14 @@ module Draper super || delegatable_method?(method) end + protected + + def self.collection_decorator_class + collection_decorator_name.constantize + rescue NameError + Draper::CollectionDecorator + end + private def delegatable_method?(method) @@ -228,20 +236,23 @@ module Draper source_class? && source_class.respond_to?(method) end - def self.inferred_source_class - uninferrable_source if name.nil? || name.demodulize !~ /.+Decorator$/ - - begin - name.chomp("Decorator").constantize - rescue NameError - uninferrable_source - end + def self.source_name + raise NameError if name.nil? || name.demodulize !~ /.+Decorator$/ + name.chomp("Decorator") end - def self.uninferrable_source + def self.inferred_source_class + source_name.constantize + rescue NameError raise Draper::UninferrableSourceError.new(self) end + def self.collection_decorator_name + plural = source_name.pluralize + raise NameError if plural == source_name + "#{plural}Decorator" + end + def self.define_proxy(method) define_method(method) do |*args, &block| source.send(method, *args, &block) diff --git a/spec/draper/collection_decorator_spec.rb b/spec/draper/collection_decorator_spec.rb index 6b85105..129ec68 100644 --- a/spec/draper/collection_decorator_spec.rb +++ b/spec/draper/collection_decorator_spec.rb @@ -248,7 +248,7 @@ describe Draper::CollectionDecorator do let(:options) { {with: ProductDecorator} } it "returns a string representation of the CollectionDecorator" do - subject.to_s.should == '#' + subject.to_s.should == '#' end end @@ -256,7 +256,15 @@ describe Draper::CollectionDecorator do let(:options) { {} } it "returns a string representation of the CollectionDecorator" do - subject.to_s.should == '#' + subject.to_s.should == '#' + end + end + + context "for a custom subclass" do + subject { ProductsDecorator.new(source) } + + it "uses the custom class name" do + subject.to_s.should =~ /ProductsDecorator/ end end end diff --git a/spec/draper/decorator_spec.rb b/spec/draper/decorator_spec.rb index 865a064..ff4ea3f 100755 --- a/spec/draper/decorator_spec.rb +++ b/spec/draper/decorator_spec.rb @@ -76,7 +76,6 @@ describe Draper::Decorator do end describe ".decorate_collection" do - subject { ProductDecorator.decorate_collection(source) } let(:source) { [Product.new, Widget.new] } describe "options validation" do @@ -92,13 +91,30 @@ describe Draper::Decorator do end end - it "returns a collection decorator" do - subject.should be_a Draper::CollectionDecorator - subject.should == source + context "when a custom collection decorator does not exist" do + subject { WidgetDecorator.decorate_collection(source) } + + it "returns a regular collection decorator" do + subject.should be_a Draper::CollectionDecorator + subject.should == source + end + + it "uses itself as the item decorator by default" do + subject.each {|item| item.should be_a WidgetDecorator} + end end - it "uses itself as the item decorator by default" do - subject.each {|item| item.should be_a ProductDecorator} + context "when a custom collection decorator exists" do + subject { ProductDecorator.decorate_collection(source) } + + it "returns the custom collection decorator" do + subject.should be_a ProductsDecorator + subject.should == source + end + + it "uses itself as the item decorator by default" do + subject.each {|item| item.should be_a ProductDecorator} + end end context "with context" do diff --git a/spec/support/dummy_app.rb b/spec/support/dummy_app.rb index b0229b9..c205f86 100644 --- a/spec/support/dummy_app.rb +++ b/spec/support/dummy_app.rb @@ -49,7 +49,8 @@ class DummyApp yield - Process.kill('KILL', out.pid) + Process.kill("KILL", out.pid) + File.delete("tmp/pids/server.pid") end end end @@ -57,11 +58,11 @@ class DummyApp private def root - File.expand_path('../../dummy', __FILE__) + File.expand_path("../../dummy", __FILE__) end def localhost - '127.0.0.1' + "127.0.0.1" end def port