Merge pull request #408 from haines/infer_collection_decorator

Infer collection decorator
This commit is contained in:
Steve Klabnik 2013-01-07 07:42:52 -08:00
commit 0b8d88fbe9
5 changed files with 58 additions and 22 deletions

View File

@ -41,7 +41,7 @@ module Draper
"inferred decorators"
end
"#<CollectionDecorator of #{klass} for #{source.inspect}>"
"#<#{self.class.name} of #{klass} for #{source.inspect}>"
end
def context=(value)

View File

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

View File

@ -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 == '#<CollectionDecorator of ProductDecorator for ["a", "b", "c"]>'
subject.to_s.should == '#<Draper::CollectionDecorator of ProductDecorator for ["a", "b", "c"]>'
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 == '#<CollectionDecorator of inferred decorators for ["a", "b", "c"]>'
subject.to_s.should == '#<Draper::CollectionDecorator of inferred decorators for ["a", "b", "c"]>'
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

View File

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

View File

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