draper 0.18.0 → 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. data/.gitignore +3 -0
  2. data/.travis.yml +5 -0
  3. data/CHANGELOG.markdown +8 -0
  4. data/Gemfile +4 -0
  5. data/Rakefile +50 -31
  6. data/Readme.markdown +42 -48
  7. data/draper.gemspec +2 -1
  8. data/lib/draper.rb +42 -7
  9. data/lib/draper/collection_decorator.rb +88 -0
  10. data/lib/draper/decoratable.rb +44 -0
  11. data/lib/draper/decorated_association.rb +55 -0
  12. data/lib/draper/decorator.rb +208 -0
  13. data/lib/draper/finders.rb +44 -0
  14. data/lib/draper/helper_proxy.rb +16 -0
  15. data/lib/draper/railtie.rb +17 -21
  16. data/lib/draper/security.rb +48 -0
  17. data/lib/draper/tasks/tu.rake +5 -0
  18. data/lib/draper/test/minitest_integration.rb +1 -1
  19. data/lib/draper/test/test_unit_integration.rb +9 -0
  20. data/lib/draper/version.rb +1 -1
  21. data/lib/draper/view_context.rb +6 -13
  22. data/lib/draper/view_helpers.rb +36 -0
  23. data/lib/generators/decorator/decorator_generator.rb +1 -1
  24. data/lib/generators/decorator/templates/decorator.rb +0 -1
  25. data/spec/draper/collection_decorator_spec.rb +240 -0
  26. data/spec/draper/decoratable_spec.rb +164 -0
  27. data/spec/draper/decorated_association_spec.rb +130 -0
  28. data/spec/draper/decorator_spec.rb +497 -0
  29. data/spec/draper/finders_spec.rb +156 -0
  30. data/spec/draper/helper_proxy_spec.rb +12 -0
  31. data/spec/draper/security_spec.rb +158 -0
  32. data/spec/draper/view_helpers_spec.rb +41 -0
  33. data/spec/dummy/.rspec +2 -0
  34. data/spec/dummy/README.rdoc +261 -0
  35. data/spec/dummy/Rakefile +7 -0
  36. data/spec/dummy/app/controllers/application_controller.rb +4 -0
  37. data/spec/dummy/app/controllers/localized_urls.rb +5 -0
  38. data/spec/dummy/app/controllers/posts_controller.rb +17 -0
  39. data/spec/dummy/app/decorators/post_decorator.rb +25 -0
  40. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  41. data/spec/dummy/app/mailers/application_mailer.rb +3 -0
  42. data/spec/dummy/app/mailers/post_mailer.rb +9 -0
  43. data/spec/dummy/app/models/post.rb +3 -0
  44. data/spec/dummy/app/views/layouts/application.html.erb +11 -0
  45. data/spec/dummy/app/views/post_mailer/decorated_email.html.erb +1 -0
  46. data/spec/dummy/app/views/posts/_post.html.erb +19 -0
  47. data/spec/dummy/app/views/posts/show.html.erb +1 -0
  48. data/spec/dummy/config.ru +4 -0
  49. data/spec/dummy/config/application.rb +64 -0
  50. data/spec/dummy/config/boot.rb +10 -0
  51. data/spec/dummy/config/database.yml +25 -0
  52. data/spec/dummy/config/environment.rb +5 -0
  53. data/spec/dummy/config/environments/development.rb +34 -0
  54. data/spec/dummy/config/environments/production.rb +55 -0
  55. data/spec/dummy/config/environments/test.rb +32 -0
  56. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  57. data/spec/dummy/config/initializers/inflections.rb +15 -0
  58. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  59. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  60. data/spec/dummy/config/initializers/session_store.rb +8 -0
  61. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  62. data/spec/dummy/config/locales/en.yml +5 -0
  63. data/spec/dummy/config/routes.rb +7 -0
  64. data/spec/dummy/db/migrate/20121019115657_create_posts.rb +8 -0
  65. data/spec/dummy/db/schema.rb +21 -0
  66. data/spec/dummy/db/seeds.rb +2 -0
  67. data/spec/dummy/lib/tasks/spec.rake +5 -0
  68. data/spec/dummy/public/404.html +26 -0
  69. data/spec/dummy/public/422.html +26 -0
  70. data/spec/dummy/public/500.html +25 -0
  71. data/spec/dummy/public/favicon.ico +0 -0
  72. data/spec/dummy/script/rails +6 -0
  73. data/spec/dummy/spec/decorators/post_decorator_spec.rb +23 -0
  74. data/spec/dummy/spec/mailers/post_mailer_spec.rb +29 -0
  75. data/spec/dummy/spec/spec_helper.rb +9 -0
  76. data/spec/generators/decorator/decorator_generator_spec.rb +3 -4
  77. data/spec/integration/integration_spec.rb +33 -0
  78. data/{performance → spec/performance}/active_record.rb +0 -0
  79. data/{performance/bechmark.rb → spec/performance/benchmark.rb} +0 -0
  80. data/{performance → spec/performance}/decorators.rb +2 -4
  81. data/{performance → spec/performance}/models.rb +0 -0
  82. data/spec/spec_helper.rb +20 -41
  83. data/spec/support/action_controller.rb +12 -0
  84. data/spec/support/active_model.rb +7 -0
  85. data/spec/support/{samples/active_record.rb → active_record.rb} +5 -0
  86. data/spec/support/{samples → decorators}/decorator_with_application_helper.rb +1 -1
  87. data/spec/support/decorators/namespaced_product_decorator.rb +5 -0
  88. data/spec/support/decorators/non_active_model_product_decorator.rb +2 -0
  89. data/spec/support/decorators/product_decorator.rb +19 -0
  90. data/spec/support/{samples → decorators}/products_decorator.rb +1 -1
  91. data/spec/support/decorators/some_thing_decorator.rb +2 -0
  92. data/spec/support/{samples → decorators}/specific_product_decorator.rb +0 -2
  93. data/spec/support/{samples → decorators}/widget_decorator.rb +0 -0
  94. data/spec/support/dummy_app.rb +84 -0
  95. data/spec/support/matchers/have_text.rb +50 -0
  96. data/spec/support/{samples → models}/namespaced_product.rb +1 -3
  97. data/spec/support/{samples → models}/non_active_model_product.rb +1 -0
  98. data/spec/support/{samples → models}/product.rb +13 -2
  99. data/spec/support/models/some_thing.rb +5 -0
  100. data/spec/support/models/uninferrable_decorator_model.rb +3 -0
  101. data/spec/support/{samples → models}/widget.rb +0 -0
  102. metadata +185 -68
  103. data/lib/draper/active_model_support.rb +0 -27
  104. data/lib/draper/base.rb +0 -312
  105. data/lib/draper/decorated_enumerable_proxy.rb +0 -90
  106. data/lib/draper/model_support.rb +0 -25
  107. data/lib/draper/rspec_integration.rb +0 -2
  108. data/lib/draper/system.rb +0 -18
  109. data/spec/draper/base_spec.rb +0 -873
  110. data/spec/draper/decorated_enumerable_proxy_spec.rb +0 -45
  111. data/spec/draper/model_support_spec.rb +0 -48
  112. data/spec/support/samples/decorator.rb +0 -5
  113. data/spec/support/samples/decorator_with_allows.rb +0 -3
  114. data/spec/support/samples/decorator_with_denies.rb +0 -3
  115. data/spec/support/samples/decorator_with_denies_all.rb +0 -3
  116. data/spec/support/samples/decorator_with_multiple_allows.rb +0 -4
  117. data/spec/support/samples/decorator_with_special_methods.rb +0 -13
  118. data/spec/support/samples/enumerable_proxy.rb +0 -3
  119. data/spec/support/samples/namespaced_product_decorator.rb +0 -7
  120. data/spec/support/samples/product_decorator.rb +0 -7
  121. data/spec/support/samples/sequel_product.rb +0 -13
  122. data/spec/support/samples/some_thing.rb +0 -2
  123. data/spec/support/samples/some_thing_decorator.rb +0 -3
@@ -0,0 +1,5 @@
1
+ if Rake::Task.task_defined?('test:run')
2
+ Rake::Task['test:run'].enhance do
3
+ Rake::Task['test:decorators'].invoke
4
+ end
5
+ end
@@ -1,7 +1,7 @@
1
1
  class MiniTest::Rails::ActiveSupport::TestCase
2
2
  # Use AS::TestCase for the base class when describing a decorator
3
3
  register_spec_type(self) do |desc|
4
- desc < Draper::Base if desc.is_a?(Class)
4
+ desc < Draper::Decorator if desc.is_a?(Class)
5
5
  end
6
6
  register_spec_type(/Decorator( ?Test)?\z/i, self)
7
7
  end
@@ -0,0 +1,9 @@
1
+ require "rake/testtask"
2
+ require "rails/test_unit/sub_test_task"
3
+
4
+ namespace :test do
5
+ Rails::SubTestTask.new(:decorators => "test:prepare") do |t|
6
+ t.libs << "test"
7
+ t.pattern = "test/decorators/**/*_test.rb"
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Draper
2
- VERSION = "0.18.0"
2
+ VERSION = "1.0.0.beta1"
3
3
  end
@@ -1,5 +1,11 @@
1
1
  module Draper
2
2
  module ViewContext
3
+ def view_context
4
+ super.tap do |context|
5
+ Draper::ViewContext.current = context
6
+ end
7
+ end
8
+
3
9
  def self.current_controller
4
10
  Thread.current[:current_controller] || ApplicationController.new
5
11
  end
@@ -16,21 +22,8 @@ module Draper
16
22
  Thread.current[:current_view_context] = context
17
23
  end
18
24
 
19
- def view_context
20
- super.tap do |context|
21
- Draper::ViewContext.current = context
22
- end
23
- end
24
-
25
- private
26
-
27
25
  def self.build_view_context
28
26
  current_controller.view_context.tap do |context|
29
- context.instance_eval do
30
- def url_options
31
- ActionMailer::Base.default_url_options
32
- end
33
- end unless context.request
34
27
  if defined?(ActionController::TestRequest)
35
28
  context.controller.request ||= ActionController::TestRequest.new
36
29
  context.request ||= context.controller.request
@@ -0,0 +1,36 @@
1
+ module Draper
2
+ module ViewHelpers
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+
7
+ # Access the helpers proxy to call built-in and user-defined
8
+ # Rails helpers from a class context.
9
+ #
10
+ # @return [HelperProxy] the helpers proxy
11
+ def helpers
12
+ @helpers ||= Draper::HelperProxy.new
13
+ end
14
+ alias_method :h, :helpers
15
+
16
+ end
17
+
18
+ # Access the helpers proxy to call built-in and user-defined
19
+ # Rails helpers. Aliased to `h` for convenience.
20
+ #
21
+ # @return [HelperProxy] the helpers proxy
22
+ def helpers
23
+ self.class.helpers
24
+ end
25
+ alias_method :h, :helpers
26
+
27
+ # Localize is something that's used quite often. Even though
28
+ # it's available through helpers, that's annoying. Aliased
29
+ # to `l` for convenience.
30
+ def localize(*args)
31
+ helpers.localize(*args)
32
+ end
33
+ alias_method :l, :localize
34
+
35
+ end
36
+ end
@@ -20,7 +20,7 @@ module Rails
20
20
  elsif defined?(ApplicationDecorator)
21
21
  "ApplicationDecorator"
22
22
  else
23
- "Draper::Base"
23
+ "Draper::Decorator"
24
24
  end
25
25
  end
26
26
  end
@@ -1,6 +1,5 @@
1
1
  <% module_namespacing do -%>
2
2
  class <%= class_name %>Decorator < <%= parent_class_name %>
3
- decorates :<%= singular_name %>
4
3
 
5
4
  # Accessing Helpers
6
5
  # You can access any helper via a proxy
@@ -0,0 +1,240 @@
1
+ require 'spec_helper'
2
+
3
+ describe Draper::CollectionDecorator do
4
+ before { ApplicationController.new.view_context }
5
+ subject { Draper::CollectionDecorator.new(source, with: ProductDecorator) }
6
+ let(:source){ [Product.new, Product.new] }
7
+ let(:non_active_model_source){ NonActiveModelProduct.new }
8
+
9
+ it "decorates a collection's items" do
10
+ subject.each do |item|
11
+ item.should be_decorated_with ProductDecorator
12
+ end
13
+ end
14
+
15
+ it "sets the decorated items' source models" do
16
+ subject.map{|item| item.source}.should == source
17
+ end
18
+
19
+ context "with options" do
20
+ subject { Draper::CollectionDecorator.new(source, with: ProductDecorator, some: "options") }
21
+
22
+ its(:options) { should == {some: "options"} }
23
+
24
+ it "passes options to the individual decorators" do
25
+ subject.each do |item|
26
+ item.options.should == {some: "options"}
27
+ end
28
+ end
29
+
30
+ describe "#options=" do
31
+ it "updates the options on the collection decorator" do
32
+ subject.options = {other: "options"}
33
+ subject.options.should == {other: "options"}
34
+ end
35
+
36
+ it "updates the options on the individual decorators" do
37
+ subject.options = {other: "options"}
38
+ subject.each do |item|
39
+ item.options.should == {other: "options"}
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "#initialize" do
46
+ context "when the :with option is given" do
47
+ context "and the decorator can't be inferred from the class" do
48
+ subject { Draper::CollectionDecorator.new(source, with: ProductDecorator) }
49
+
50
+ it "uses the :with option" do
51
+ subject.decorator_class.should be ProductDecorator
52
+ end
53
+ end
54
+
55
+ context "and the decorator is inferrable from the class" do
56
+ subject { ProductsDecorator.new(source, with: SpecificProductDecorator) }
57
+
58
+ it "uses the :with option" do
59
+ subject.decorator_class.should be SpecificProductDecorator
60
+ end
61
+ end
62
+ end
63
+
64
+ context "when the :with option is not given" do
65
+ context "and the decorator can't be inferred from the class" do
66
+ it "raises an UninferrableDecoratorError" do
67
+ expect{Draper::CollectionDecorator.new(source)}.to raise_error Draper::UninferrableDecoratorError
68
+ end
69
+ end
70
+
71
+ context "and the decorator is inferrable from the class" do
72
+ subject { ProductsDecorator.new(source) }
73
+
74
+ it "infers the decorator" do
75
+ subject.decorator_class.should be ProductDecorator
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "#source" do
82
+ it "returns the source collection" do
83
+ subject.source.should be source
84
+ end
85
+
86
+ it "is aliased to #to_source" do
87
+ subject.to_source.should be source
88
+ end
89
+ end
90
+
91
+ describe "#find" do
92
+ context "with a block" do
93
+ it "decorates Enumerable#find" do
94
+ subject.decorated_collection.should_receive(:find)
95
+ subject.find {|p| p.title == "title" }
96
+ end
97
+ end
98
+
99
+ context "without a block" do
100
+ it "decorates Model.find" do
101
+ source.should_not_receive(:find)
102
+ Product.should_receive(:find).with(1).and_return(:product)
103
+ subject.find(1).should == ProductDecorator.new(:product)
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "#helpers" do
109
+ it "returns a HelperProxy" do
110
+ subject.helpers.should be_a Draper::HelperProxy
111
+ end
112
+
113
+ it "is aliased to #h" do
114
+ subject.h.should be subject.helpers
115
+ end
116
+
117
+ it "initializes the wrapper only once" do
118
+ helper_proxy = subject.helpers
119
+ helper_proxy.stub(:test_method) { "test_method" }
120
+ subject.helpers.test_method.should == "test_method"
121
+ subject.helpers.test_method.should == "test_method"
122
+ end
123
+ end
124
+
125
+ describe "#localize" do
126
+ before { subject.helpers.should_receive(:localize).with(:an_object, {some: "options"}) }
127
+
128
+ it "delegates to helpers" do
129
+ subject.localize(:an_object, some: "options")
130
+ end
131
+
132
+ it "is aliased to #l" do
133
+ subject.l(:an_object, some: "options")
134
+ end
135
+ end
136
+
137
+ describe ".helpers" do
138
+ it "returns a HelperProxy" do
139
+ subject.class.helpers.should be_a Draper::HelperProxy
140
+ end
141
+
142
+ it "is aliased to .h" do
143
+ subject.class.h.should be subject.class.helpers
144
+ end
145
+ end
146
+
147
+ describe "#to_ary" do
148
+ # required for `render @collection` in Rails
149
+ it "delegates to the decorated collection" do
150
+ subject.decorated_collection.should_receive(:to_ary).and_return(:an_array)
151
+ subject.to_ary.should == :an_array
152
+ end
153
+ end
154
+
155
+ describe "#respond_to?" do
156
+ it "returns true for its own methods" do
157
+ subject.should respond_to :decorated_collection
158
+ end
159
+
160
+ it "returns true for the wrapped collection's methods" do
161
+ source.stub(:respond_to?).with(:whatever, true).and_return(true)
162
+ subject.respond_to?(:whatever, true).should be_true
163
+ end
164
+ end
165
+
166
+ context "Array methods" do
167
+ describe "#include?" do
168
+ it "delegates to the decorated collection" do
169
+ subject.decorated_collection.should_receive(:include?).with(:something).and_return(true)
170
+ subject.should include :something
171
+ end
172
+ end
173
+
174
+ describe "#[]" do
175
+ it "delegates to the decorated collection" do
176
+ subject.decorated_collection.should_receive(:[]).with(42).and_return(:something)
177
+ subject[42].should == :something
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "#==" do
183
+ context "when comparing to a collection decorator with the same source" do
184
+ it "returns true" do
185
+ a = Draper::CollectionDecorator.new(source, with: ProductDecorator)
186
+ b = ProductsDecorator.new(source)
187
+ a.should == b
188
+ end
189
+ end
190
+
191
+ context "when comparing to a collection decorator with a different source" do
192
+ it "returns false" do
193
+ a = Draper::CollectionDecorator.new(source, with: ProductDecorator)
194
+ b = ProductsDecorator.new([Product.new])
195
+ a.should_not == b
196
+ end
197
+ end
198
+
199
+ context "when comparing to a collection of the same items" do
200
+ it "returns true" do
201
+ a = Draper::CollectionDecorator.new(source, with: ProductDecorator)
202
+ b = source.dup
203
+ a.should == b
204
+ end
205
+ end
206
+
207
+ context "when comparing to a collection of different items" do
208
+ it "returns true" do
209
+ a = Draper::CollectionDecorator.new(source, with: ProductDecorator)
210
+ b = [Product.new]
211
+ a.should_not == b
212
+ end
213
+ end
214
+ end
215
+
216
+ it "pretends to be the source class" do
217
+ subject.kind_of?(source.class).should be_true
218
+ subject.is_a?(source.class).should be_true
219
+ end
220
+
221
+ it "is still its own class" do
222
+ subject.kind_of?(subject.class).should be_true
223
+ subject.is_a?(subject.class).should be_true
224
+ end
225
+
226
+ describe "#method_missing" do
227
+ before do
228
+ class << source
229
+ def page_number
230
+ 42
231
+ end
232
+ end
233
+ end
234
+
235
+ it "proxies unknown methods to the source collection" do
236
+ subject.page_number.should == 42
237
+ end
238
+ end
239
+
240
+ end
@@ -0,0 +1,164 @@
1
+ require 'spec_helper'
2
+
3
+ describe Draper::Decoratable do
4
+ subject { Product.new }
5
+
6
+ describe "#decorate" do
7
+ it "returns a decorator for self" do
8
+ subject.decorate.should be_a ProductDecorator
9
+ subject.decorate.source.should be subject
10
+ end
11
+
12
+ it "accepts options" do
13
+ decorator = subject.decorate(some: "options")
14
+ decorator.options.should == {some: "options"}
15
+ end
16
+
17
+ it "is not memoized" do
18
+ subject.decorate.should_not be subject.decorate
19
+ end
20
+ end
21
+
22
+ describe "#applied_decorators" do
23
+ it "returns an empty list" do
24
+ subject.applied_decorators.should be_empty
25
+ end
26
+ end
27
+
28
+ describe "#decorated_with?" do
29
+ it "returns false" do
30
+ subject.should_not be_decorated_with ProductDecorator
31
+ end
32
+ end
33
+
34
+ describe "#decorated?" do
35
+ it "returns false" do
36
+ subject.should_not be_decorated
37
+ end
38
+ end
39
+
40
+ describe "#decorator_class" do
41
+ it "delegates to .decorator_class" do
42
+ Product.stub(:decorator_class).and_return(WidgetDecorator)
43
+ product = Product.new
44
+ product.decorator_class.should be WidgetDecorator
45
+ end
46
+ end
47
+
48
+ describe "#===" do
49
+ context "with itself" do
50
+ it "returns true" do
51
+ (subject === subject).should be_true
52
+ end
53
+ end
54
+
55
+ context "with another instance" do
56
+ it "returns false" do
57
+ (subject === Product.new).should be_false
58
+ end
59
+ end
60
+
61
+ context "with a decorated version of itself" do
62
+ it "returns true" do
63
+ decorator = double(source: subject)
64
+ (subject === decorator).should be_true
65
+ end
66
+ end
67
+
68
+ context "with a decorated other instance" do
69
+ it "returns false" do
70
+ decorator = double(source: Product.new)
71
+ (subject === decorator).should be_false
72
+ end
73
+ end
74
+ end
75
+
76
+ describe ".====" do
77
+ context "with an instance" do
78
+ it "returns true" do
79
+ (Product === Product.new).should be_true
80
+ end
81
+ end
82
+
83
+ context "with a derived instance" do
84
+ it "returns true" do
85
+ (Product === Widget.new).should be_true
86
+ end
87
+ end
88
+
89
+ context "with an unrelated instance" do
90
+ it "returns false" do
91
+ (Product === Object.new).should be_false
92
+ end
93
+ end
94
+
95
+ context "with a decorated instance" do
96
+ it "returns true" do
97
+ decorator = double(source: Product.new)
98
+ (Product === decorator).should be_true
99
+ end
100
+ end
101
+
102
+ context "with a decorated derived instance" do
103
+ it "returns true" do
104
+ decorator = double(source: Widget.new)
105
+ (Product === decorator).should be_true
106
+ end
107
+ end
108
+
109
+ context "with a decorated unrelated instance" do
110
+ it "returns false" do
111
+ decorator = double(source: Object.new)
112
+ (Product === decorator).should be_false
113
+ end
114
+ end
115
+ end
116
+
117
+ describe ".decorate" do
118
+ it "returns a collection decorator" do
119
+ Product.stub(:scoped).and_return([Product.new])
120
+ Product.stub(:decorator_class).and_return(WidgetDecorator)
121
+ decorator = Product.decorate
122
+
123
+ decorator.should be_a Draper::CollectionDecorator
124
+ decorator.decorator_class.should be WidgetDecorator
125
+ decorator.source.should be Product.scoped
126
+ end
127
+
128
+ it "accepts options" do
129
+ decorator = Product.decorate(some: "options")
130
+ decorator.options.should == {some: "options"}
131
+ end
132
+
133
+ it "is not memoized" do
134
+ Product.decorate.should_not be Product.decorate
135
+ end
136
+ end
137
+
138
+ describe ".decorator_class" do
139
+ context "for non-ActiveModel classes" do
140
+ it "infers the decorator from the class" do
141
+ NonActiveModelProduct.decorator_class.should be NonActiveModelProductDecorator
142
+ end
143
+ end
144
+
145
+ context "for ActiveModel classes" do
146
+ it "infers the decorator from the model name" do
147
+ Product.stub(:model_name).and_return("Widget")
148
+ Product.decorator_class.should be WidgetDecorator
149
+ end
150
+ end
151
+
152
+ context "for namespaced ActiveModel classes" do
153
+ it "infers the decorator from the model name" do
154
+ Namespace::Product.decorator_class.should be Namespace::ProductDecorator
155
+ end
156
+ end
157
+
158
+ context "when the decorator can't be inferred" do
159
+ it "throws an UninferrableDecoratorError" do
160
+ expect{UninferrableDecoratorModel.decorator_class}.to raise_error Draper::UninferrableDecoratorError
161
+ end
162
+ end
163
+ end
164
+ end