Let decorator_class infer anonymous class' decorator from superclass (#820)
* Let decorator_class infer anonymous class' decorator from superclass * Replace constantize with safe_constantize on decorator's private methods * Don't raise NameError on decorator private methods. To prevent rescuing and checking if NameError is from internal decorator private methods, we change to return nil on these private methods. * Revise decorator inferred_object_class and collection_decorator_name based on code review comments
This commit is contained in:
parent
815c4186dd
commit
cc23669889
|
@ -72,9 +72,9 @@ module Draper
|
||||||
def decorator_class
|
def decorator_class
|
||||||
prefix = respond_to?(:model_name) ? model_name : name
|
prefix = respond_to?(:model_name) ? model_name : name
|
||||||
decorator_name = "#{prefix}Decorator"
|
decorator_name = "#{prefix}Decorator"
|
||||||
decorator_name.constantize
|
decorator_name_constant = decorator_name.safe_constantize
|
||||||
rescue NameError => error
|
return decorator_name_constant unless decorator_name_constant.nil?
|
||||||
raise unless error.missing_name?(decorator_name)
|
|
||||||
if superclass.respond_to?(:decorator_class)
|
if superclass.respond_to?(:decorator_class)
|
||||||
superclass.decorator_class
|
superclass.decorator_class
|
||||||
else
|
else
|
||||||
|
|
|
@ -225,9 +225,9 @@ module Draper
|
||||||
# @return [Class] the class created by {decorate_collection}.
|
# @return [Class] the class created by {decorate_collection}.
|
||||||
def self.collection_decorator_class
|
def self.collection_decorator_class
|
||||||
name = collection_decorator_name
|
name = collection_decorator_name
|
||||||
name.constantize
|
name_constant = name && name.safe_constantize
|
||||||
rescue NameError
|
|
||||||
Draper::CollectionDecorator
|
name_constant || Draper::CollectionDecorator
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -242,22 +242,23 @@ module Draper
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.object_class_name
|
def self.object_class_name
|
||||||
raise NameError if name.nil? || name.demodulize !~ /.+Decorator$/
|
return nil if name.nil? || name.demodulize !~ /.+Decorator$/
|
||||||
name.chomp("Decorator")
|
name.chomp("Decorator")
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.inferred_object_class
|
def self.inferred_object_class
|
||||||
name = object_class_name
|
name = object_class_name
|
||||||
name.constantize
|
name_constant = name && name.safe_constantize
|
||||||
rescue NameError => error
|
return name_constant unless name_constant.nil?
|
||||||
raise if name && !error.missing_name?(name)
|
|
||||||
raise Draper::UninferrableObjectError.new(self)
|
raise Draper::UninferrableObjectError.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.collection_decorator_name
|
def self.collection_decorator_name
|
||||||
plural = object_class_name.pluralize
|
singular = object_class_name
|
||||||
raise NameError if plural == object_class_name
|
plural = singular && singular.pluralize
|
||||||
"#{plural}Decorator"
|
|
||||||
|
"#{plural}Decorator" unless plural == singular
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_multiple_decoration(options)
|
def handle_multiple_decoration(options)
|
||||||
|
|
|
@ -205,10 +205,22 @@ module Draper
|
||||||
|
|
||||||
context "when an unrelated NameError is thrown" do
|
context "when an unrelated NameError is thrown" do
|
||||||
it "re-raises that error" do
|
it "re-raises that error" do
|
||||||
allow_any_instance_of(String).to receive(:constantize) { Draper::Base }
|
# Not related to safe_constantize behavior, we just want to raise a NameError inside the function
|
||||||
|
allow_any_instance_of(String).to receive(:safe_constantize) { Draper::Base }
|
||||||
expect{Product.decorator_class}.to raise_error NameError, /Draper::Base/
|
expect{Product.decorator_class}.to raise_error NameError, /Draper::Base/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "when an anonymous class is given" do
|
||||||
|
it "infers the decorator from a superclass" do
|
||||||
|
anonymous_class = Class.new(Product) do
|
||||||
|
def self.name
|
||||||
|
to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
expect(anonymous_class.decorator_class).to be ProductDecorator
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -202,7 +202,8 @@ module Draper
|
||||||
|
|
||||||
context "when an unrelated NameError is thrown" do
|
context "when an unrelated NameError is thrown" do
|
||||||
it "re-raises that error" do
|
it "re-raises that error" do
|
||||||
allow_any_instance_of(String).to receive(:constantize) { SomethingThatDoesntExist }
|
# Not related to safe_constantize behavior, we just want to raise a NameError inside the function
|
||||||
|
allow_any_instance_of(String).to receive(:safe_constantize) { SomethingThatDoesntExist }
|
||||||
expect{ProductDecorator.object_class}.to raise_error NameError, /SomethingThatDoesntExist/
|
expect{ProductDecorator.object_class}.to raise_error NameError, /SomethingThatDoesntExist/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -225,7 +226,7 @@ module Draper
|
||||||
|
|
||||||
describe '.collection_decorator_class' do
|
describe '.collection_decorator_class' do
|
||||||
it 'defaults to CollectionDecorator' do
|
it 'defaults to CollectionDecorator' do
|
||||||
allow_any_instance_of(String).to receive(:constantize) { SomethingThatDoesntExist }
|
allow_any_instance_of(String).to receive(:safe_constantize) { nil }
|
||||||
expect(ProductDecorator.collection_decorator_class).to be Draper::CollectionDecorator
|
expect(ProductDecorator.collection_decorator_class).to be Draper::CollectionDecorator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue