From 09ad84fb712a30dd4302b9daa03d11281ac7d169 Mon Sep 17 00:00:00 2001 From: Andrew Haines Date: Tue, 5 Mar 2013 22:28:03 +0000 Subject: [PATCH] Rescue specific NameErrors when inferring classes The previous behavior swallowed genuine NameErrors (as opposed to failure to find the inferred class), for example when the user has not updated the decorator base class from Draper::Base. --- lib/draper/decoratable.rb | 3 ++- lib/draper/decorator.rb | 12 ++++++++---- spec/draper/decoratable_spec.rb | 7 +++++++ spec/draper/decorator_spec.rb | 25 +++++++++++++++++++++---- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/draper/decoratable.rb b/lib/draper/decoratable.rb index de74e39..f77111a 100644 --- a/lib/draper/decoratable.rb +++ b/lib/draper/decoratable.rb @@ -68,7 +68,8 @@ module Draper decorator_name = [(namespace && namespace.name), "#{prefix}Decorator"].compact.join("::") decorator_name.constantize - rescue NameError + rescue NameError => error + raise unless error.missing_name?(decorator_name) raise Draper::UninferrableDecoratorError.new(self) end diff --git a/lib/draper/decorator.rb b/lib/draper/decorator.rb index 793fcea..3341ef0 100755 --- a/lib/draper/decorator.rb +++ b/lib/draper/decorator.rb @@ -212,8 +212,10 @@ module Draper # @return [Class] the class created by {decorate_collection}. def self.collection_decorator_class(namespace=nil) - collection_decorator_name(namespace).constantize - rescue NameError + name = collection_decorator_name(namespace) + name.constantize + rescue NameError => error + raise if name && !error.missing_name?(name) Draper::CollectionDecorator end @@ -225,8 +227,10 @@ module Draper end def self.inferred_source_class - source_name.constantize - rescue NameError + name = source_name + name.constantize + rescue NameError => error + raise if name && !error.missing_name?(name) raise Draper::UninferrableSourceError.new(self) end diff --git a/spec/draper/decoratable_spec.rb b/spec/draper/decoratable_spec.rb index 67d0730..ca8f635 100644 --- a/spec/draper/decoratable_spec.rb +++ b/spec/draper/decoratable_spec.rb @@ -179,6 +179,13 @@ module Draper expect{Model.decorator_class}.to raise_error UninferrableDecoratorError end end + + context "when an unrelated NameError is thrown" do + it "re-raises that error" do + String.any_instance.stub(:constantize).and_return{Draper::Base} + expect{Product.decorator_class}.to raise_error NameError, /Draper::Base/ + end + end end end diff --git a/spec/draper/decorator_spec.rb b/spec/draper/decorator_spec.rb index f44c063..9d0e346 100755 --- a/spec/draper/decorator_spec.rb +++ b/spec/draper/decorator_spec.rb @@ -154,6 +154,13 @@ module Draper Decorator.decorate_collection(source, with: nil, namespace: DecoratorNamespace) end end + + context "when a NameError is thrown" do + it "re-raises that error" do + String.any_instance.stub(:constantize).and_return{Draper::DecoratedEnumerableProxy} + expect{ProductDecorator.decorate_collection([])}.to raise_error NameError, /Draper::DecoratedEnumerableProxy/ + end + end end describe ".decorates" do @@ -179,20 +186,23 @@ module Draper end describe ".source_class" do + protect_class ProductDecorator + protect_class Namespaced::ProductDecorator + context "when not set by .decorates" do - it "raises an error for a so-named 'Decorator'" do + it "raises an UninferrableSourceError for a so-named 'Decorator'" do expect{Decorator.source_class}.to raise_error UninferrableSourceError end - it "raises an error for anonymous decorators" do + it "raises an UninferrableSourceError for anonymous decorators" do expect{Class.new(Decorator).source_class}.to raise_error UninferrableSourceError end - it "raises an error for a decorator without a model" do + it "raises an UninferrableSourceError for a decorator without a model" do expect{OtherDecorator.source_class}.to raise_error UninferrableSourceError end - it "raises an error for other naming conventions" do + it "raises an UninferrableSourceError for other naming conventions" do expect{ProductPresenter.source_class}.to raise_error UninferrableSourceError end @@ -203,6 +213,13 @@ module Draper it "infers namespaced sources" do expect(Namespaced::ProductDecorator.source_class).to be Namespaced::Product end + + context "when an unrelated NameError is thrown" do + it "re-raises that error" do + String.any_instance.stub(:constantize).and_return{SomethingThatDoesntExist} + expect{ProductDecorator.source_class}.to raise_error NameError, /SomethingThatDoesntExist/ + end + end end end