Merge pull request #408 from haines/infer_collection_decorator
Infer collection decorator
This commit is contained in:
commit
0b8d88fbe9
|
@ -41,7 +41,7 @@ module Draper
|
||||||
"inferred decorators"
|
"inferred decorators"
|
||||||
end
|
end
|
||||||
|
|
||||||
"#<CollectionDecorator of #{klass} for #{source.inspect}>"
|
"#<#{self.class.name} of #{klass} for #{source.inspect}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
def context=(value)
|
def context=(value)
|
||||||
|
|
|
@ -141,7 +141,7 @@ module Draper
|
||||||
# @option options [Hash] :context context available to decorated items
|
# @option options [Hash] :context context available to decorated items
|
||||||
def self.decorate_collection(source, options = {})
|
def self.decorate_collection(source, options = {})
|
||||||
options.assert_valid_keys(:with, :context)
|
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
|
end
|
||||||
|
|
||||||
# Get the chain of decorators applied to the object.
|
# Get the chain of decorators applied to the object.
|
||||||
|
@ -218,6 +218,14 @@ module Draper
|
||||||
super || delegatable_method?(method)
|
super || delegatable_method?(method)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def self.collection_decorator_class
|
||||||
|
collection_decorator_name.constantize
|
||||||
|
rescue NameError
|
||||||
|
Draper::CollectionDecorator
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def delegatable_method?(method)
|
def delegatable_method?(method)
|
||||||
|
@ -228,18 +236,21 @@ module Draper
|
||||||
source_class? && source_class.respond_to?(method)
|
source_class? && source_class.respond_to?(method)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.source_name
|
||||||
|
raise NameError if name.nil? || name.demodulize !~ /.+Decorator$/
|
||||||
|
name.chomp("Decorator")
|
||||||
|
end
|
||||||
|
|
||||||
def self.inferred_source_class
|
def self.inferred_source_class
|
||||||
uninferrable_source if name.nil? || name.demodulize !~ /.+Decorator$/
|
source_name.constantize
|
||||||
|
|
||||||
begin
|
|
||||||
name.chomp("Decorator").constantize
|
|
||||||
rescue NameError
|
rescue NameError
|
||||||
uninferrable_source
|
raise Draper::UninferrableSourceError.new(self)
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.uninferrable_source
|
def self.collection_decorator_name
|
||||||
raise Draper::UninferrableSourceError.new(self)
|
plural = source_name.pluralize
|
||||||
|
raise NameError if plural == source_name
|
||||||
|
"#{plural}Decorator"
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.define_proxy(method)
|
def self.define_proxy(method)
|
||||||
|
|
|
@ -248,7 +248,7 @@ describe Draper::CollectionDecorator do
|
||||||
let(:options) { {with: ProductDecorator} }
|
let(:options) { {with: ProductDecorator} }
|
||||||
|
|
||||||
it "returns a string representation of the CollectionDecorator" do
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -256,7 +256,15 @@ describe Draper::CollectionDecorator do
|
||||||
let(:options) { {} }
|
let(:options) { {} }
|
||||||
|
|
||||||
it "returns a string representation of the CollectionDecorator" do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -76,7 +76,6 @@ describe Draper::Decorator do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe ".decorate_collection" do
|
describe ".decorate_collection" do
|
||||||
subject { ProductDecorator.decorate_collection(source) }
|
|
||||||
let(:source) { [Product.new, Widget.new] }
|
let(:source) { [Product.new, Widget.new] }
|
||||||
|
|
||||||
describe "options validation" do
|
describe "options validation" do
|
||||||
|
@ -92,14 +91,31 @@ describe Draper::Decorator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns a collection decorator" do
|
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 be_a Draper::CollectionDecorator
|
||||||
subject.should == source
|
subject.should == source
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "uses itself as the item decorator by default" do
|
||||||
|
subject.each {|item| item.should be_a WidgetDecorator}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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
|
it "uses itself as the item decorator by default" do
|
||||||
subject.each {|item| item.should be_a ProductDecorator}
|
subject.each {|item| item.should be_a ProductDecorator}
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "with context" do
|
context "with context" do
|
||||||
subject { ProductDecorator.decorate_collection(source, with: :infer, context: {some: 'context'}) }
|
subject { ProductDecorator.decorate_collection(source, with: :infer, context: {some: 'context'}) }
|
||||||
|
|
|
@ -49,7 +49,8 @@ class DummyApp
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
Process.kill('KILL', out.pid)
|
Process.kill("KILL", out.pid)
|
||||||
|
File.delete("tmp/pids/server.pid")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,11 +58,11 @@ class DummyApp
|
||||||
private
|
private
|
||||||
|
|
||||||
def root
|
def root
|
||||||
File.expand_path('../../dummy', __FILE__)
|
File.expand_path("../../dummy", __FILE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
def localhost
|
def localhost
|
||||||
'127.0.0.1'
|
"127.0.0.1"
|
||||||
end
|
end
|
||||||
|
|
||||||
def port
|
def port
|
||||||
|
|
Loading…
Reference in New Issue