draper 1.0.0.beta1 → 1.0.0.beta2
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.
- data/CHANGELOG.markdown +35 -0
- data/draper.gemspec +2 -2
- data/lib/draper.rb +6 -0
- data/lib/draper/decorator.rb +71 -19
- data/lib/draper/finders.rb +5 -15
- data/lib/draper/version.rb +1 -1
- data/spec/draper/decorator_spec.rb +203 -78
- data/spec/draper/finders_spec.rb +0 -11
- data/spec/dummy/app/decorators/post_decorator.rb +4 -0
- data/spec/dummy/spec/decorators/post_decorator_spec.rb +3 -0
- data/spec/generators/decorator/decorator_generator_spec.rb +2 -2
- data/spec/support/decorators/namespaced_product_decorator.rb +1 -1
- data/spec/support/decorators/product_decorator.rb +5 -1
- data/spec/support/models/product.rb +4 -0
- metadata +7 -7
data/CHANGELOG.markdown
CHANGED
@@ -1,5 +1,40 @@
|
|
1
1
|
# Draper Changelog
|
2
2
|
|
3
|
+
## 1.0.0.beta2
|
4
|
+
|
5
|
+
* `has_finders` is now `decorates_finders`. [https://github.com/haines/draper/commit/33f18aa062e0d3848443dbd81047f20d5665579f](https://github.com/haines/draper/commit/33f18aa062e0d3848443dbd81047f20d5665579f)
|
6
|
+
|
7
|
+
* If a finder method is used, and the source class is not set and cannot be inferred, an `UninferrableSourceError` is raised. [https://github.com/haines/draper/commit/8ef5bf2f02f7033e3cd4f1f5de7397b02c984fe3](https://github.com/haines/draper/commit/8ef5bf2f02f7033e3cd4f1f5de7397b02c984fe3)
|
8
|
+
|
9
|
+
* Class methods are now properly delegated again. [https://github.com/haines/draper/commit/731995a5feac4cd06cf9328d2892c0eca9992db6](https://github.com/haines/draper/commit/731995a5feac4cd06cf9328d2892c0eca9992db6)
|
10
|
+
|
11
|
+
* We no longer `respond_to?` private methods on the source. [https://github.com/haines/draper/commit/18ebac81533a6413aa20a3c26f23e91d0b12b031](https://github.com/haines/draper/commit/18ebac81533a6413aa20a3c26f23e91d0b12b031)
|
12
|
+
|
13
|
+
* Rails versioning relaxed to support Rails 4 [https://github.com/drapergem/draper/commit/8bfd393b5baa7aa1488076a5e2cb88648efaa815](https://github.com/drapergem/draper/commit/8bfd393b5baa7aa1488076a5e2cb88648efaa815)
|
14
|
+
|
15
|
+
## 1.0.0.beta1
|
16
|
+
|
17
|
+
* Renaming `Draper::Base` to `Draper::Decorator`. This is the most significant
|
18
|
+
change you'll need to upgrade your application. [https://github.com/drapergem/draper/commit/025742cb3b295d259cf0ecf3669c24817d6f2df1](https://github.com/drapergem/draper/commit/025742cb3b295d259cf0ecf3669c24817d6f2df1)
|
19
|
+
* Added an internal Rails application for integration tests. This won't affect
|
20
|
+
your application, but we're now running a set of Cucumber tests inside of a
|
21
|
+
Rails app in both development and production mode to help ensure that we
|
22
|
+
don't make changes that break Draper. [https://github.com/drapergem/draper/commit/90a4859085cab158658d23d77cd3108b6037e36f](https://github.com/drapergem/draper/commit/90a4859085cab158658d23d77cd3108b6037e36f)
|
23
|
+
* Add `#decorated?` method. This gives us a free RSpec matcher,
|
24
|
+
`is_decorated?`. [https://github.com/drapergem/draper/commit/834a6fd1f24b5646c333a04a99fe9846a58965d6](https://github.com/drapergem/draper/commit/834a6fd1f24b5646c333a04a99fe9846a58965d6)
|
25
|
+
* `#decorates` is no longer needed inside your models, and should be removed.
|
26
|
+
Decorators automatically infer the class they decorate. [https://github.com/drapergem/draper/commit/e1214d97b62f2cab45227cc650029734160dcdfe](https://github.com/drapergem/draper/commit/e1214d97b62f2cab45227cc650029734160dcdfe)
|
27
|
+
* Decorators do not automatically come with 'finders' by default. If you'd like
|
28
|
+
to use `SomeDecorator.find(1)`, for example, simply add `#has_finders` to
|
29
|
+
the decorator to include them. [https://github.com/drapergem/draper/commit/42b6f78fda4f51845dab4d35da68880f1989d178](https://github.com/drapergem/draper/commit/42b6f78fda4f51845dab4d35da68880f1989d178)
|
30
|
+
* To refer to the object being decorated, `#source` is now the preferred
|
31
|
+
method. [https://github.com/drapergem/draper/commit/1e84fcb4a0eab0d12f5feda6886ce1caa239cb16](https://github.com/drapergem/draper/commit/1e84fcb4a0eab0d12f5feda6886ce1caa239cb16)
|
32
|
+
* `ActiveModel::Serialization` is included in Decorators if you've requred
|
33
|
+
`ActiveModel::Serializers`, so that decorators can be serialized. [https://github.com/drapergem/draper/commit/c4b352799067506849abcbf14963ea36abda301c](https://github.com/drapergem/draper/commit/c4b352799067506849abcbf14963ea36abda301c)
|
34
|
+
* Properly support Test::Unit [https://github.com/drapergem/draper/commit/087e134ed0885ec11325ffabe8ab2bebef77a33a](https://github.com/drapergem/draper/commit/087e134ed0885ec11325ffabe8ab2bebef77a33a)
|
35
|
+
|
36
|
+
And many small bug fixes and refactorings.
|
37
|
+
|
3
38
|
## 0.18.0
|
4
39
|
|
5
40
|
* [Adds the ability to decorate an enumerable proxy](https://github.com/drapergem/draper/commit/67c7125192740a7586a3a635acd735ae01b97837)
|
data/draper.gemspec
CHANGED
@@ -16,8 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_dependency 'activesupport', '
|
20
|
-
s.add_dependency 'actionpack', '
|
19
|
+
s.add_dependency 'activesupport', '>= 3.2'
|
20
|
+
s.add_dependency 'actionpack', '>= 3.2'
|
21
21
|
|
22
22
|
s.add_development_dependency 'ammeter'
|
23
23
|
s.add_development_dependency 'rake', '~> 0.9.2'
|
data/lib/draper.rb
CHANGED
data/lib/draper/decorator.rb
CHANGED
@@ -34,18 +34,36 @@ module Draper
|
|
34
34
|
alias_method :decorate, :new
|
35
35
|
end
|
36
36
|
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
37
|
+
# Specify the class that this class decorates.
|
38
|
+
#
|
39
|
+
# @param [String, Symbol, Class] Class or name of class to decorate.
|
40
|
+
def self.decorates(klass)
|
41
|
+
@source_class = klass.to_s.classify.constantize
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Class] The source class corresponding to this
|
45
|
+
# decorator class
|
46
|
+
def self.source_class
|
47
|
+
@source_class ||= inferred_source_class
|
48
|
+
end
|
49
|
+
|
50
|
+
# Checks whether this decorator class has a corresponding
|
51
|
+
# source class
|
52
|
+
def self.source_class?
|
53
|
+
source_class
|
54
|
+
rescue Draper::UninferrableSourceError
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
# Automatically decorates ActiveRecord finder methods, so that
|
59
|
+
# you can use `ProductDecorator.find(id)` instead of
|
40
60
|
# `ProductDecorator.decorate(Product.find(id))`.
|
41
61
|
#
|
42
|
-
#
|
43
|
-
# inferred from the decorator class.
|
62
|
+
# The model class to be found is defined by `decorates` or
|
63
|
+
# inferred from the decorator class name.
|
44
64
|
#
|
45
|
-
|
46
|
-
def self.has_finders(options = {})
|
65
|
+
def self.decorates_finders
|
47
66
|
extend Draper::Finders
|
48
|
-
self.finder_class = options[:for] || name.chomp("Decorator")
|
49
67
|
end
|
50
68
|
|
51
69
|
# Typically called within a decorator definition, this method causes
|
@@ -145,10 +163,6 @@ module Draper
|
|
145
163
|
end
|
146
164
|
alias_method :is_a?, :kind_of?
|
147
165
|
|
148
|
-
def respond_to?(method, include_private = false)
|
149
|
-
super || (allow?(method) && source.respond_to?(method, include_private))
|
150
|
-
end
|
151
|
-
|
152
166
|
# We always want to delegate present, in case we decorate a nil object.
|
153
167
|
#
|
154
168
|
# I don't like the idea of decorating a nil object, but we'll deal with
|
@@ -157,8 +171,18 @@ module Draper
|
|
157
171
|
source.present?
|
158
172
|
end
|
159
173
|
|
174
|
+
# For ActiveModel compatibilty
|
175
|
+
def to_model
|
176
|
+
self
|
177
|
+
end
|
178
|
+
|
179
|
+
# For ActiveModel compatibility
|
180
|
+
def to_param
|
181
|
+
source.to_param
|
182
|
+
end
|
183
|
+
|
160
184
|
def method_missing(method, *args, &block)
|
161
|
-
if
|
185
|
+
if delegatable_method?(method)
|
162
186
|
self.class.define_proxy(method)
|
163
187
|
send(method, *args, &block)
|
164
188
|
else
|
@@ -166,18 +190,46 @@ module Draper
|
|
166
190
|
end
|
167
191
|
end
|
168
192
|
|
169
|
-
|
170
|
-
|
171
|
-
self
|
193
|
+
def respond_to?(method, include_private = false)
|
194
|
+
super || delegatable_method?(method)
|
172
195
|
end
|
173
196
|
|
174
|
-
|
175
|
-
|
176
|
-
|
197
|
+
def self.method_missing(method, *args, &block)
|
198
|
+
if delegatable_method?(method)
|
199
|
+
source_class.send(method, *args, &block)
|
200
|
+
else
|
201
|
+
super
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def self.respond_to?(method, include_private = false)
|
206
|
+
super || delegatable_method?(method)
|
177
207
|
end
|
178
208
|
|
179
209
|
private
|
180
210
|
|
211
|
+
def delegatable_method?(method)
|
212
|
+
allow?(method) && source.respond_to?(method)
|
213
|
+
end
|
214
|
+
|
215
|
+
def self.delegatable_method?(method)
|
216
|
+
source_class? && source_class.respond_to?(method)
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.inferred_source_class
|
220
|
+
uninferrable_source if name.nil? || name.demodulize !~ /.+Decorator$/
|
221
|
+
|
222
|
+
begin
|
223
|
+
name.chomp("Decorator").constantize
|
224
|
+
rescue NameError
|
225
|
+
uninferrable_source
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.uninferrable_source
|
230
|
+
raise Draper::UninferrableSourceError.new(self)
|
231
|
+
end
|
232
|
+
|
181
233
|
def self.define_proxy(method)
|
182
234
|
define_method(method) do |*args, &block|
|
183
235
|
source.send(method, *args, &block)
|
data/lib/draper/finders.rb
CHANGED
@@ -1,29 +1,24 @@
|
|
1
1
|
module Draper
|
2
2
|
module Finders
|
3
3
|
|
4
|
-
attr_reader :finder_class
|
5
|
-
def finder_class=(klass)
|
6
|
-
@finder_class = klass.to_s.camelize.constantize
|
7
|
-
end
|
8
|
-
|
9
4
|
def find(id, options = {})
|
10
|
-
decorate(
|
5
|
+
decorate(source_class.find(id), options)
|
11
6
|
end
|
12
7
|
|
13
8
|
def all(options = {})
|
14
|
-
decorate_collection(
|
9
|
+
decorate_collection(source_class.all, options)
|
15
10
|
end
|
16
11
|
|
17
12
|
def first(options = {})
|
18
|
-
decorate(
|
13
|
+
decorate(source_class.first, options)
|
19
14
|
end
|
20
15
|
|
21
16
|
def last(options = {})
|
22
|
-
decorate(
|
17
|
+
decorate(source_class.last, options)
|
23
18
|
end
|
24
19
|
|
25
20
|
def method_missing(method, *args, &block)
|
26
|
-
result =
|
21
|
+
result = super
|
27
22
|
options = args.extract_options!
|
28
23
|
|
29
24
|
case method.to_s
|
@@ -35,10 +30,5 @@ module Draper
|
|
35
30
|
result
|
36
31
|
end
|
37
32
|
end
|
38
|
-
|
39
|
-
def respond_to?(method, include_private = false)
|
40
|
-
super || finder_class.respond_to?(method)
|
41
|
-
end
|
42
|
-
|
43
33
|
end
|
44
34
|
end
|
data/lib/draper/version.rb
CHANGED
@@ -125,6 +125,97 @@ describe Draper::Decorator do
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
|
+
describe ".decorates" do
|
129
|
+
subject { Class.new(Draper::Decorator) }
|
130
|
+
|
131
|
+
context "with a symbol" do
|
132
|
+
it "sets .source_class" do
|
133
|
+
subject.decorates :product
|
134
|
+
subject.source_class.should be Product
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "with a string" do
|
139
|
+
it "sets .source_class" do
|
140
|
+
subject.decorates "product"
|
141
|
+
subject.source_class.should be Product
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "with a class" do
|
146
|
+
it "sets .source_class" do
|
147
|
+
subject.decorates Product
|
148
|
+
subject.source_class.should be Product
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe ".source_class" do
|
154
|
+
context "when not set by .decorates" do
|
155
|
+
context "for an anonymous decorator" do
|
156
|
+
subject { Class.new(Draper::Decorator) }
|
157
|
+
|
158
|
+
it "raises an UninferrableSourceError" do
|
159
|
+
expect{subject.source_class}.to raise_error Draper::UninferrableSourceError
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "for a decorator without a corresponding source" do
|
164
|
+
subject { SpecificProductDecorator }
|
165
|
+
|
166
|
+
it "raises an UninferrableSourceError" do
|
167
|
+
expect{subject.source_class}.to raise_error Draper::UninferrableSourceError
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "for a decorator called Decorator" do
|
172
|
+
subject { Draper::Decorator }
|
173
|
+
|
174
|
+
it "raises an UninferrableSourceError" do
|
175
|
+
expect{subject.source_class}.to raise_error Draper::UninferrableSourceError
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context "for a decorator with a name not ending in Decorator" do
|
180
|
+
subject { DecoratorWithApplicationHelper }
|
181
|
+
|
182
|
+
it "raises an UninferrableSourceError" do
|
183
|
+
expect{subject.source_class}.to raise_error Draper::UninferrableSourceError
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context "for an inferrable source" do
|
188
|
+
subject { ProductDecorator }
|
189
|
+
|
190
|
+
it "infers the source" do
|
191
|
+
subject.source_class.should be Product
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "for a namespaced inferrable source" do
|
196
|
+
subject { Namespace::ProductDecorator }
|
197
|
+
|
198
|
+
it "infers the namespaced source" do
|
199
|
+
subject.source_class.should be Namespace::Product
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe ".source_class?" do
|
206
|
+
subject { Class.new(Draper::Decorator) }
|
207
|
+
|
208
|
+
it "returns truthy when .source_class is set" do
|
209
|
+
subject.stub(:source_class).and_return(Product)
|
210
|
+
subject.source_class?.should be_true
|
211
|
+
end
|
212
|
+
|
213
|
+
it "returns false when .source_class is not inferrable" do
|
214
|
+
subject.stub(:source_class).and_raise(Draper::UninferrableSourceError.new(subject))
|
215
|
+
subject.source_class?.should be_false
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
128
219
|
describe ".decorates_association" do
|
129
220
|
let(:decorator_class) { Class.new(ProductDecorator) }
|
130
221
|
before { decorator_class.decorates_association :similar_products, with: ProductDecorator }
|
@@ -298,8 +389,8 @@ describe Draper::Decorator do
|
|
298
389
|
subject.respond_to?(:awesome_private_title, true).should be_true
|
299
390
|
end
|
300
391
|
|
301
|
-
it "returns
|
302
|
-
subject.respond_to?(:private_title, true).should
|
392
|
+
it "returns false for the source's private methods" do
|
393
|
+
subject.respond_to?(:private_title, true).should be_false
|
303
394
|
end
|
304
395
|
end
|
305
396
|
|
@@ -327,63 +418,110 @@ describe Draper::Decorator do
|
|
327
418
|
end
|
328
419
|
end
|
329
420
|
|
330
|
-
describe "
|
331
|
-
|
421
|
+
describe ".respond_to?" do
|
422
|
+
subject { Class.new(ProductDecorator) }
|
332
423
|
|
333
|
-
|
334
|
-
|
335
|
-
|
424
|
+
context "without a source class" do
|
425
|
+
it "returns true for its own class methods" do
|
426
|
+
subject.should respond_to :my_class_method
|
427
|
+
end
|
336
428
|
|
337
|
-
|
338
|
-
|
429
|
+
it "returns false for other class methods" do
|
430
|
+
subject.should_not respond_to :sample_class_method
|
431
|
+
end
|
339
432
|
end
|
340
433
|
|
341
|
-
|
342
|
-
|
343
|
-
subject.hello_world.should be :proxied
|
344
|
-
end
|
434
|
+
context "with a source_class" do
|
435
|
+
before { subject.decorates :product }
|
345
436
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
subject.methods.should include :hello_world
|
350
|
-
end
|
437
|
+
it "returns true for its own class methods" do
|
438
|
+
subject.should respond_to :my_class_method
|
439
|
+
end
|
351
440
|
|
352
|
-
|
353
|
-
|
441
|
+
it "returns true for the source's class methods" do
|
442
|
+
subject.should respond_to :sample_class_method
|
443
|
+
end
|
354
444
|
end
|
445
|
+
end
|
355
446
|
|
356
|
-
|
357
|
-
|
358
|
-
|
447
|
+
describe "proxying" do
|
448
|
+
context "instance methods" do
|
449
|
+
let(:decorator_class) { Class.new(ProductDecorator) }
|
359
450
|
|
360
|
-
|
361
|
-
|
362
|
-
|
451
|
+
it "does not proxy methods that are defined on the decorator" do
|
452
|
+
subject.overridable.should be :overridden
|
453
|
+
end
|
363
454
|
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
subject.class.allows :hello_world
|
455
|
+
it "does not proxy methods inherited from Object" do
|
456
|
+
subject.inspect.should_not be source.inspect
|
457
|
+
end
|
368
458
|
|
459
|
+
it "proxies missing methods that exist on the source" do
|
460
|
+
source.stub(:hello_world).and_return(:proxied)
|
369
461
|
subject.hello_world.should be :proxied
|
370
|
-
expect{subject.goodnight_moon}.to raise_error NameError
|
371
462
|
end
|
372
463
|
|
373
|
-
it "
|
374
|
-
|
375
|
-
subject.
|
464
|
+
it "adds proxied methods to the decorator when they are used" do
|
465
|
+
subject.methods.should_not include :hello_world
|
466
|
+
subject.hello_world
|
467
|
+
subject.methods.should include :hello_world
|
468
|
+
end
|
376
469
|
|
377
|
-
|
378
|
-
|
470
|
+
it "passes blocks to proxied methods" do
|
471
|
+
subject.block{"marker"}.should == "marker"
|
379
472
|
end
|
380
473
|
|
381
|
-
it "
|
382
|
-
|
383
|
-
|
474
|
+
it "does not confuse Kernel#Array" do
|
475
|
+
Array(subject).should be_a Array
|
476
|
+
end
|
477
|
+
|
478
|
+
it "proxies delegated methods" do
|
479
|
+
subject.delegated_method.should == "Yay, delegation"
|
480
|
+
end
|
481
|
+
|
482
|
+
it "does not proxy private methods" do
|
483
|
+
expect{subject.private_title}.to raise_error NoMethodError
|
484
|
+
end
|
485
|
+
|
486
|
+
context "with method security" do
|
487
|
+
it "respects allows" do
|
488
|
+
source.stub(:hello_world, :goodnight_moon).and_return(:proxied)
|
489
|
+
subject.class.allows :hello_world
|
490
|
+
|
491
|
+
subject.hello_world.should be :proxied
|
492
|
+
expect{subject.goodnight_moon}.to raise_error NameError
|
493
|
+
end
|
494
|
+
|
495
|
+
it "respects denies" do
|
496
|
+
source.stub(:hello_world, :goodnight_moon).and_return(:proxied)
|
497
|
+
subject.class.denies :goodnight_moon
|
498
|
+
|
499
|
+
subject.hello_world.should be :proxied
|
500
|
+
expect{subject.goodnight_moon}.to raise_error NameError
|
501
|
+
end
|
502
|
+
|
503
|
+
it "respects denies_all" do
|
504
|
+
source.stub(:hello_world, :goodnight_moon).and_return(:proxied)
|
505
|
+
subject.class.denies_all
|
506
|
+
|
507
|
+
expect{subject.hello_world}.to raise_error NameError
|
508
|
+
expect{subject.goodnight_moon}.to raise_error NameError
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|
384
512
|
|
385
|
-
|
386
|
-
|
513
|
+
context "class methods" do
|
514
|
+
subject { Class.new(ProductDecorator) }
|
515
|
+
let(:source_class) { Product }
|
516
|
+
before { subject.decorates source_class }
|
517
|
+
|
518
|
+
it "does not proxy methods that are defined on the decorator" do
|
519
|
+
subject.overridable.should be :overridden
|
520
|
+
end
|
521
|
+
|
522
|
+
it "proxies missing methods that exist on the source" do
|
523
|
+
source_class.stub(:hello_world).and_return(:proxied)
|
524
|
+
subject.hello_world.should be :proxied
|
387
525
|
end
|
388
526
|
end
|
389
527
|
end
|
@@ -421,7 +559,7 @@ describe Draper::Decorator do
|
|
421
559
|
end
|
422
560
|
|
423
561
|
it "is able to use the link_to helper" do
|
424
|
-
subject.sample_link.should ==
|
562
|
+
subject.sample_link.should == %{<a href="/World">Hello</a>}
|
425
563
|
end
|
426
564
|
|
427
565
|
it "is able to use the truncate helper" do
|
@@ -443,55 +581,42 @@ describe Draper::Decorator do
|
|
443
581
|
subject.is_a?(subject.class).should be_true
|
444
582
|
end
|
445
583
|
|
446
|
-
describe ".
|
584
|
+
describe ".decorates_finders" do
|
447
585
|
it "extends the Finders module" do
|
448
586
|
ProductDecorator.should be_a_kind_of Draper::Finders
|
449
587
|
end
|
588
|
+
end
|
450
589
|
|
451
|
-
|
452
|
-
|
453
|
-
ProductDecorator.finder_class.should be Product
|
454
|
-
end
|
590
|
+
describe "#serializable_hash" do
|
591
|
+
let(:decorator_class) { ProductDecorator }
|
455
592
|
|
456
|
-
|
457
|
-
|
458
|
-
Namespace::ProductDecorator.finder_class.should be Namespace::Product
|
459
|
-
end
|
460
|
-
end
|
593
|
+
it "serializes overridden attributes" do
|
594
|
+
subject.serializable_hash[:overridable].should be :overridden
|
461
595
|
end
|
596
|
+
end
|
462
597
|
|
463
|
-
|
464
|
-
|
598
|
+
describe ".method_missing" do
|
599
|
+
context "when called on an anonymous decorator" do
|
600
|
+
subject { ->{ Class.new(Draper::Decorator).fizzbuzz } }
|
601
|
+
it { should raise_error NoMethodError }
|
602
|
+
end
|
465
603
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
end
|
471
|
-
end
|
604
|
+
context "when called on an uninferrable decorator" do
|
605
|
+
subject { ->{ SpecificProductDecorator.fizzbuzz } }
|
606
|
+
it { should raise_error NoMethodError }
|
607
|
+
end
|
472
608
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
end
|
609
|
+
context "when called on an inferrable decorator" do
|
610
|
+
context "for a method known to the inferred class" do
|
611
|
+
subject { ->{ ProductDecorator.model_name } }
|
612
|
+
it { should_not raise_error }
|
478
613
|
end
|
479
614
|
|
480
|
-
context "
|
481
|
-
|
482
|
-
|
483
|
-
subject.finder_class.should be Namespace::Product
|
484
|
-
end
|
615
|
+
context "for a method unknown to the inferred class" do
|
616
|
+
subject { ->{ ProductDecorator.fizzbuzz } }
|
617
|
+
it { should raise_error NoMethodError }
|
485
618
|
end
|
486
619
|
end
|
487
620
|
end
|
488
621
|
|
489
|
-
describe "#serializable_hash" do
|
490
|
-
let(:decorator_class) { ProductDecorator }
|
491
|
-
|
492
|
-
it "serializes overridden attributes" do
|
493
|
-
subject.serializable_hash[:overridable].should be :overridden
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
622
|
end
|
data/spec/draper/finders_spec.rb
CHANGED
@@ -142,15 +142,4 @@ describe Draper::Finders do
|
|
142
142
|
ProductDecorator.where(name: "apples").should be found
|
143
143
|
end
|
144
144
|
end
|
145
|
-
|
146
|
-
describe ".respond_to?" do
|
147
|
-
it "responds to the model's class methods" do
|
148
|
-
ProductDecorator.should respond_to :sample_class_method
|
149
|
-
end
|
150
|
-
|
151
|
-
it "responds to its own methods" do
|
152
|
-
ProductDecorator.should respond_to :my_class_method
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
145
|
end
|
@@ -30,7 +30,7 @@ describe Rails::Generators::DecoratorGenerator do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'parent decorator' do
|
33
|
-
describe 'decorator
|
33
|
+
describe 'decorator inherited from Draper::Decorator' do
|
34
34
|
before { run_generator ["YourModel"] }
|
35
35
|
|
36
36
|
subject { file('app/decorators/your_model_decorator.rb') }
|
@@ -38,7 +38,7 @@ describe Rails::Generators::DecoratorGenerator do
|
|
38
38
|
it { should contain "class YourModelDecorator < Draper::Decorator" }
|
39
39
|
end
|
40
40
|
|
41
|
-
describe "decorator
|
41
|
+
describe "decorator inherited from ApplicationDecorator if it's present" do
|
42
42
|
before do
|
43
43
|
class ApplicationDecorator; end
|
44
44
|
run_generator ["YourModel"]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class ProductDecorator < Draper::Decorator
|
2
|
-
|
2
|
+
decorates_finders
|
3
3
|
|
4
4
|
def awesome_title
|
5
5
|
"Awesome Title"
|
@@ -9,6 +9,10 @@ class ProductDecorator < Draper::Decorator
|
|
9
9
|
:overridden
|
10
10
|
end
|
11
11
|
|
12
|
+
def self.overridable
|
13
|
+
:overridden
|
14
|
+
end
|
15
|
+
|
12
16
|
def self.my_class_method
|
13
17
|
end
|
14
18
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: draper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta2
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,14 +10,14 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-12-03 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
|
-
- -
|
20
|
+
- - ! '>='
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '3.2'
|
23
23
|
type: :runtime
|
@@ -25,7 +25,7 @@ dependencies:
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
none: false
|
27
27
|
requirements:
|
28
|
-
- -
|
28
|
+
- - ! '>='
|
29
29
|
- !ruby/object:Gem::Version
|
30
30
|
version: '3.2'
|
31
31
|
- !ruby/object:Gem::Dependency
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
34
34
|
none: false
|
35
35
|
requirements:
|
36
|
-
- -
|
36
|
+
- - ! '>='
|
37
37
|
- !ruby/object:Gem::Version
|
38
38
|
version: '3.2'
|
39
39
|
type: :runtime
|
@@ -41,7 +41,7 @@ dependencies:
|
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
|
-
- -
|
44
|
+
- - ! '>='
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '3.2'
|
47
47
|
- !ruby/object:Gem::Dependency
|
@@ -276,7 +276,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
276
276
|
version: '0'
|
277
277
|
segments:
|
278
278
|
- 0
|
279
|
-
hash:
|
279
|
+
hash: 3275361325961868093
|
280
280
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
281
281
|
none: false
|
282
282
|
requirements:
|