draper 0.12.1 → 0.17.0
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/.gitignore +5 -1
- data/.rspec +1 -0
- data/.travis.yml +3 -5
- data/CHANGELOG.markdown +51 -0
- data/Readme.markdown +32 -17
- data/draper.gemspec +6 -9
- data/lib/draper/active_model_support.rb +16 -13
- data/lib/draper/base.rb +54 -11
- data/lib/draper/decorated_enumerable_proxy.rb +13 -6
- data/lib/draper/railtie.rb +16 -15
- data/lib/draper/rspec_integration.rb +2 -33
- data/lib/draper/system.rb +3 -14
- data/lib/draper/test/minitest_integration.rb +26 -0
- data/lib/draper/test/rspec_integration.rb +28 -0
- data/lib/draper/test/view_context.rb +12 -0
- data/lib/draper/version.rb +1 -1
- data/lib/draper/view_context.rb +5 -9
- data/lib/draper.rb +3 -1
- data/lib/generators/decorator/templates/decorator.rb +1 -1
- data/lib/generators/test_unit/templates/decorator_test.rb +1 -1
- data/spec/draper/base_spec.rb +206 -88
- data/spec/draper/model_support_spec.rb +5 -5
- data/spec/draper/view_context_spec.rb +18 -7
- data/spec/generators/decorator/decorator_generator_spec.rb +4 -0
- data/spec/spec_helper.rb +12 -2
- data/spec/support/samples/application_controller.rb +10 -11
- data/spec/support/samples/application_helper.rb +3 -0
- data/spec/support/samples/decorator_with_allows.rb +0 -0
- data/spec/support/samples/decorator_with_application_helper.rb +4 -0
- data/spec/support/samples/decorator_with_denies_all.rb +3 -0
- data/spec/support/samples/decorator_with_special_methods.rb +13 -0
- data/spec/support/samples/sequel_product.rb +13 -0
- metadata +103 -159
- data/CHANGELOG.txt +0 -23
|
@@ -27,7 +27,7 @@ class <%= class_name %>Decorator < <%= parent_class_name %>
|
|
|
27
27
|
# generated by ActiveRecord:
|
|
28
28
|
#
|
|
29
29
|
# def created_at
|
|
30
|
-
# h.content_tag :span,
|
|
30
|
+
# h.content_tag :span, attributes["created_at"].strftime("%a %m/%d/%y"),
|
|
31
31
|
# :class => 'timestamp'
|
|
32
32
|
# end
|
|
33
33
|
end
|
data/spec/draper/base_spec.rb
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Draper::Base do
|
|
4
|
-
before(:each){ ApplicationController.new.
|
|
4
|
+
before(:each){ ApplicationController.new.view_context }
|
|
5
5
|
subject{ Decorator.new(source) }
|
|
6
6
|
let(:source){ Product.new }
|
|
7
7
|
let(:non_active_model_source){ NonActiveModelProduct.new }
|
|
8
8
|
|
|
9
9
|
context("proxying class methods") do
|
|
10
|
-
it "
|
|
10
|
+
it "pass missing class method calls on to the wrapped class" do
|
|
11
11
|
subject.class.sample_class_method.should == "sample class method"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
it "
|
|
14
|
+
it "respond_to a wrapped class method" do
|
|
15
15
|
subject.class.should respond_to(:sample_class_method)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
it "
|
|
18
|
+
it "still respond_to its own class methods" do
|
|
19
19
|
subject.class.should respond_to(:own_class_method)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
context(".helpers") do
|
|
24
|
-
it "
|
|
24
|
+
it "have a valid view_context" do
|
|
25
25
|
subject.helpers.should be
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
it "
|
|
28
|
+
it "is aliased to .h" do
|
|
29
29
|
subject.h.should == subject.helpers
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
context("#helpers") do
|
|
34
|
-
it "
|
|
34
|
+
it "have a valid view_context" do
|
|
35
35
|
Decorator.helpers.should be
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
-
it "
|
|
38
|
+
it "is aliased to #h" do
|
|
39
39
|
Decorator.h.should == Decorator.helpers
|
|
40
40
|
end
|
|
41
41
|
end
|
|
@@ -50,14 +50,14 @@ describe Draper::Base do
|
|
|
50
50
|
ProductDecorator.new(product_decorator).model.should be_instance_of Product
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
it "
|
|
53
|
+
it "handle plural-like words properly'" do
|
|
54
54
|
class Business; end
|
|
55
55
|
expect do
|
|
56
56
|
class BusinessDecorator < Draper::Base
|
|
57
57
|
decorates:business
|
|
58
58
|
end
|
|
59
59
|
BusinessDecorator.model_class.should == Business
|
|
60
|
-
end.
|
|
60
|
+
end.to_not raise_error
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
context("accepts ActiveRecord like :class_name option too") do
|
|
@@ -67,7 +67,7 @@ describe Draper::Base do
|
|
|
67
67
|
decorates :product, :class => Product
|
|
68
68
|
end
|
|
69
69
|
CustomDecorator.model_class.should == Product
|
|
70
|
-
end.
|
|
70
|
+
end.to_not raise_error
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
it "accepts constants for :class_name" do
|
|
@@ -76,7 +76,7 @@ describe Draper::Base do
|
|
|
76
76
|
decorates :product, :class_name => Product
|
|
77
77
|
end
|
|
78
78
|
CustomDecorator.model_class.should == Product
|
|
79
|
-
end.
|
|
79
|
+
end.to_not raise_error
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
it "accepts strings for :class" do
|
|
@@ -85,7 +85,7 @@ describe Draper::Base do
|
|
|
85
85
|
decorates :product, :class => 'Product'
|
|
86
86
|
end
|
|
87
87
|
CustomDecorator.model_class.should == Product
|
|
88
|
-
end.
|
|
88
|
+
end.to_not raise_error
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
it "accepts strings for :class_name" do
|
|
@@ -94,7 +94,7 @@ describe Draper::Base do
|
|
|
94
94
|
decorates :product, :class_name => 'Product'
|
|
95
95
|
end
|
|
96
96
|
CustomDecorator.model_class.should == Product
|
|
97
|
-
end.
|
|
97
|
+
end.to_not raise_error
|
|
98
98
|
end
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -154,6 +154,14 @@ describe Draper::Base do
|
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
+
context "with a scope specified" do
|
|
158
|
+
before(:each){ subject.class_eval{ decorates_association :thing, :scope => :foo } }
|
|
159
|
+
it "applies the scope before decoration" do
|
|
160
|
+
SomeThing.any_instance.should_receive(:foo).and_return(:bar)
|
|
161
|
+
subject.thing.model.should == :bar
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
157
165
|
context "for a polymorphic association" do
|
|
158
166
|
before(:each){ subject.class_eval{ decorates_association :thing, :polymorphic => true } }
|
|
159
167
|
it "causes the association to be decorated with the right decorator" do
|
|
@@ -170,27 +178,50 @@ describe Draper::Base do
|
|
|
170
178
|
subject.previous_version.should be_nil
|
|
171
179
|
end
|
|
172
180
|
end
|
|
181
|
+
|
|
182
|
+
context "#find" do
|
|
183
|
+
before(:each){ subject.class_eval{ decorates_association :similar_products } }
|
|
184
|
+
context "with a block" do
|
|
185
|
+
it "delegates to #each" do
|
|
186
|
+
subject.similar_products.source.should_receive :find
|
|
187
|
+
subject.similar_products.find {|p| p.title == "title" }
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
context "without a block" do
|
|
192
|
+
it "calls a finder method" do
|
|
193
|
+
subject.similar_products.source.should_not_receive :find
|
|
194
|
+
subject.similar_products.find 1
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
173
198
|
end
|
|
174
199
|
|
|
175
200
|
context('.decorates_associations') do
|
|
176
201
|
subject { Decorator }
|
|
177
202
|
it "decorates each of the associations" do
|
|
178
|
-
subject.should_receive(:decorates_association).with(:similar_products)
|
|
179
|
-
subject.should_receive(:decorates_association).with(:previous_version)
|
|
203
|
+
subject.should_receive(:decorates_association).with(:similar_products, {})
|
|
204
|
+
subject.should_receive(:decorates_association).with(:previous_version, {})
|
|
180
205
|
|
|
181
206
|
subject.decorates_associations :similar_products, :previous_version
|
|
182
207
|
end
|
|
208
|
+
|
|
209
|
+
it "dispatches options" do
|
|
210
|
+
subject.should_receive(:decorates_association).with(:similar_products, :with => ProductDecorator)
|
|
211
|
+
subject.should_receive(:decorates_association).with(:previous_version, :with => ProductDecorator)
|
|
212
|
+
|
|
213
|
+
subject.decorates_associations :similar_products, :previous_version, :with => ProductDecorator
|
|
214
|
+
end
|
|
183
215
|
end
|
|
184
216
|
|
|
185
|
-
context(".
|
|
186
|
-
it "
|
|
187
|
-
subject.
|
|
188
|
-
subject.model.should == source
|
|
217
|
+
context(".wrapped_object") do
|
|
218
|
+
it "return the wrapped object" do
|
|
219
|
+
subject.wrapped_object.should == source
|
|
189
220
|
end
|
|
190
221
|
end
|
|
191
222
|
|
|
192
223
|
context(".source / .to_source") do
|
|
193
|
-
it "
|
|
224
|
+
it "return the wrapped object" do
|
|
194
225
|
subject.to_source == source
|
|
195
226
|
subject.source == source
|
|
196
227
|
end
|
|
@@ -205,40 +236,43 @@ describe Draper::Base do
|
|
|
205
236
|
end
|
|
206
237
|
end
|
|
207
238
|
|
|
208
|
-
it "
|
|
239
|
+
it "not override a defined method with a source method" do
|
|
209
240
|
DecoratorWithApplicationHelper.new(source).length.should == "overridden"
|
|
210
241
|
end
|
|
211
242
|
|
|
212
|
-
it "
|
|
243
|
+
it "not copy the .class, .inspect, or other existing methods" do
|
|
213
244
|
source.class.should_not == subject.class
|
|
214
245
|
source.inspect.should_not == subject.inspect
|
|
215
246
|
source.to_s.should_not == subject.to_s
|
|
216
247
|
end
|
|
217
248
|
|
|
218
249
|
context "when an ActiveModel descendant" do
|
|
219
|
-
it "
|
|
250
|
+
it "always proxy to_param if it is not defined on the decorator itself" do
|
|
220
251
|
source.stub(:to_param).and_return(1)
|
|
221
252
|
Draper::Base.new(source).to_param.should == 1
|
|
222
253
|
end
|
|
223
254
|
|
|
224
|
-
it "
|
|
255
|
+
it "always proxy id if it is not defined on the decorator itself" do
|
|
225
256
|
source.stub(:id).and_return(123456789)
|
|
226
257
|
Draper::Base.new(source).id.should == 123456789
|
|
227
258
|
end
|
|
228
259
|
|
|
229
|
-
it "
|
|
260
|
+
it "always proxy errors if it is not defined on the decorator itself" do
|
|
230
261
|
Draper::Base.new(source).errors.should be_an_instance_of ActiveModel::Errors
|
|
231
262
|
end
|
|
232
|
-
end
|
|
233
263
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
Draper::Base.new(non_active_model_source).to_param.should_not == 1
|
|
264
|
+
it "never proxy to_param if it is defined on the decorator itself" do
|
|
265
|
+
source.stub(:to_param).and_return(1)
|
|
266
|
+
DecoratorWithSpecialMethods.new(source).to_param.should == "foo"
|
|
238
267
|
end
|
|
239
268
|
|
|
240
|
-
it "
|
|
241
|
-
|
|
269
|
+
it "never proxy id if it is defined on the decorator itself" do
|
|
270
|
+
source.stub(:id).and_return(123456789)
|
|
271
|
+
DecoratorWithSpecialMethods.new(source).id.should == 1337
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
it "never proxy errors if it is defined on the decorator itself" do
|
|
275
|
+
DecoratorWithSpecialMethods.new(source).errors.should be_an_instance_of Array
|
|
242
276
|
end
|
|
243
277
|
end
|
|
244
278
|
end
|
|
@@ -253,24 +287,24 @@ describe Draper::Base do
|
|
|
253
287
|
end
|
|
254
288
|
end
|
|
255
289
|
|
|
256
|
-
it "
|
|
290
|
+
it "wrap source methods so they still accept blocks" do
|
|
257
291
|
subject.block{"marker"}.should == "marker"
|
|
258
292
|
end
|
|
259
293
|
|
|
260
294
|
context ".find" do
|
|
261
|
-
it "
|
|
295
|
+
it "lookup the associated model when passed an integer" do
|
|
262
296
|
pd = ProductDecorator.find(1)
|
|
263
297
|
pd.should be_instance_of(ProductDecorator)
|
|
264
298
|
pd.model.should be_instance_of(Product)
|
|
265
299
|
end
|
|
266
300
|
|
|
267
|
-
it "
|
|
301
|
+
it "lookup the associated model when passed a string" do
|
|
268
302
|
pd = ProductDecorator.find("1")
|
|
269
303
|
pd.should be_instance_of(ProductDecorator)
|
|
270
304
|
pd.model.should be_instance_of(Product)
|
|
271
305
|
end
|
|
272
306
|
|
|
273
|
-
it "
|
|
307
|
+
it "accept and store a context" do
|
|
274
308
|
pd = ProductDecorator.find(1, :context => :admin)
|
|
275
309
|
pd.context.should == :admin
|
|
276
310
|
end
|
|
@@ -342,6 +376,15 @@ describe Draper::Base do
|
|
|
342
376
|
end
|
|
343
377
|
end
|
|
344
378
|
|
|
379
|
+
context "when given a collection of sequel models" do
|
|
380
|
+
# Sequel models implement #each
|
|
381
|
+
let(:source) { [SequelProduct.new, SequelProduct.new] }
|
|
382
|
+
|
|
383
|
+
it "returns a collection of wrapped objects" do
|
|
384
|
+
subject.each{ |decorated| decorated.should be_instance_of(Draper::Base) }
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
345
388
|
context "when given a single source object" do
|
|
346
389
|
let(:source) { Product.new }
|
|
347
390
|
|
|
@@ -440,32 +483,35 @@ describe Draper::Base do
|
|
|
440
483
|
end
|
|
441
484
|
|
|
442
485
|
context('.==') do
|
|
443
|
-
it "
|
|
486
|
+
it "compare the decorated models" do
|
|
444
487
|
other = Draper::Base.new(source)
|
|
445
488
|
subject.should == other
|
|
446
489
|
end
|
|
447
490
|
end
|
|
448
491
|
|
|
449
492
|
context ".respond_to?" do
|
|
450
|
-
|
|
493
|
+
# respond_to? is called by some proxies (id, to_param, errors).
|
|
494
|
+
# This is, why I stub it this way.
|
|
495
|
+
it "delegate respond_to? to the decorated model" do
|
|
451
496
|
other = Draper::Base.new(source)
|
|
452
|
-
source.
|
|
453
|
-
|
|
497
|
+
source.stub(:respond_to?).and_return(false)
|
|
498
|
+
source.stub(:respond_to?).with(:whatever, true).once.and_return("mocked")
|
|
499
|
+
subject.respond_to?(:whatever, true).should == "mocked"
|
|
454
500
|
end
|
|
455
501
|
end
|
|
456
502
|
|
|
457
503
|
context 'position accessors' do
|
|
458
504
|
[:first, :last].each do |method|
|
|
459
505
|
context "##{method}" do
|
|
460
|
-
it "
|
|
506
|
+
it "return a decorated instance" do
|
|
461
507
|
ProductDecorator.send(method).should be_instance_of ProductDecorator
|
|
462
508
|
end
|
|
463
509
|
|
|
464
|
-
it "
|
|
510
|
+
it "return the #{method} instance of the wrapped class" do
|
|
465
511
|
ProductDecorator.send(method).model.should == Product.send(method)
|
|
466
512
|
end
|
|
467
513
|
|
|
468
|
-
it "
|
|
514
|
+
it "accept an optional context" do
|
|
469
515
|
ProductDecorator.send(method, :context => :admin).context.should == :admin
|
|
470
516
|
end
|
|
471
517
|
end
|
|
@@ -486,32 +532,32 @@ describe Draper::Base do
|
|
|
486
532
|
let(:empty_collection) { [] }
|
|
487
533
|
subject { ProductDecorator.decorate(paged_array) }
|
|
488
534
|
|
|
489
|
-
it "
|
|
535
|
+
it "proxy all calls to decorated collection" do
|
|
490
536
|
paged_array.page_number.should == "magic_value"
|
|
491
537
|
subject.page_number.should == "magic_value"
|
|
492
538
|
end
|
|
493
539
|
|
|
494
|
-
it "
|
|
540
|
+
it "support Rails partial lookup for a collection" do
|
|
495
541
|
# to support Rails render @collection the returned collection
|
|
496
542
|
# (or its proxy) should implement #to_ary.
|
|
497
543
|
subject.respond_to?(:to_ary).should be true
|
|
498
544
|
subject.to_ary.first.should == ProductDecorator.decorate(paged_array.first)
|
|
499
545
|
end
|
|
500
546
|
|
|
501
|
-
it "
|
|
547
|
+
it "delegate respond_to? to the wrapped collection" do
|
|
502
548
|
decorator = ProductDecorator.decorate(paged_array)
|
|
503
549
|
paged_array.should_receive(:respond_to?).with(:whatever, true)
|
|
504
550
|
decorator.respond_to?(:whatever, true)
|
|
505
551
|
end
|
|
506
552
|
|
|
507
|
-
it "
|
|
553
|
+
it "return blank for a decorated empty collection" do
|
|
508
554
|
# This tests that respond_to? is defined for the DecoratedEnumerableProxy
|
|
509
555
|
# since activesupport calls respond_to?(:empty) in #blank
|
|
510
556
|
decorator = ProductDecorator.decorate(empty_collection)
|
|
511
557
|
decorator.should be_blank
|
|
512
558
|
end
|
|
513
559
|
|
|
514
|
-
it "
|
|
560
|
+
it "return whether the member is in the array for a decorated wrapped collection" do
|
|
515
561
|
# This tests that include? is defined for the DecoratedEnumerableProxy
|
|
516
562
|
member = paged_array.first
|
|
517
563
|
subject.respond_to?(:include?)
|
|
@@ -520,20 +566,20 @@ describe Draper::Base do
|
|
|
520
566
|
subject.include?(Product.new).should == false
|
|
521
567
|
end
|
|
522
568
|
|
|
523
|
-
it "
|
|
569
|
+
it "equal each other when decorating the same collection" do
|
|
524
570
|
subject_one = ProductDecorator.decorate(paged_array)
|
|
525
571
|
subject_two = ProductDecorator.decorate(paged_array)
|
|
526
572
|
subject_one.should == subject_two
|
|
527
573
|
end
|
|
528
574
|
|
|
529
|
-
it "
|
|
575
|
+
it "not equal each other when decorating different collections" do
|
|
530
576
|
subject_one = ProductDecorator.decorate(paged_array)
|
|
531
577
|
new_paged_array = paged_array + [Product.new]
|
|
532
578
|
subject_two = ProductDecorator.decorate(new_paged_array)
|
|
533
579
|
subject_one.should_not == subject_two
|
|
534
580
|
end
|
|
535
581
|
|
|
536
|
-
it "
|
|
582
|
+
it "allow decorated access by index" do
|
|
537
583
|
subject = ProductDecorator.decorate(paged_array)
|
|
538
584
|
subject[0].should be_instance_of ProductDecorator
|
|
539
585
|
end
|
|
@@ -559,18 +605,18 @@ describe Draper::Base do
|
|
|
559
605
|
end
|
|
560
606
|
|
|
561
607
|
context '#all' do
|
|
562
|
-
it "
|
|
608
|
+
it "return a decorated collection" do
|
|
563
609
|
ProductDecorator.all.first.should be_instance_of ProductDecorator
|
|
564
610
|
end
|
|
565
611
|
|
|
566
|
-
it "
|
|
612
|
+
it "accept a context" do
|
|
567
613
|
collection = ProductDecorator.all(:context => :admin)
|
|
568
614
|
collection.first.context.should == :admin
|
|
569
615
|
end
|
|
570
616
|
end
|
|
571
617
|
|
|
572
618
|
context(".source / .to_source") do
|
|
573
|
-
it "
|
|
619
|
+
it "return the wrapped object" do
|
|
574
620
|
subject.to_source == source
|
|
575
621
|
subject.source == source
|
|
576
622
|
end
|
|
@@ -580,19 +626,19 @@ describe Draper::Base do
|
|
|
580
626
|
describe "a sample usage with denies" do
|
|
581
627
|
let(:subject_with_denies){ DecoratorWithDenies.new(source) }
|
|
582
628
|
|
|
583
|
-
it "
|
|
629
|
+
it "proxy methods not listed in denies" do
|
|
584
630
|
subject_with_denies.should respond_to(:hello_world)
|
|
585
631
|
end
|
|
586
632
|
|
|
587
|
-
it "
|
|
633
|
+
it "not echo methods specified with denies" do
|
|
588
634
|
subject_with_denies.should_not respond_to(:goodnight_moon)
|
|
589
635
|
end
|
|
590
636
|
|
|
591
|
-
it "
|
|
637
|
+
it "not clobber other decorators' methods" do
|
|
592
638
|
subject.should respond_to(:hello_world)
|
|
593
639
|
end
|
|
594
640
|
|
|
595
|
-
it "
|
|
641
|
+
it "not allow method_missing to circumvent a deny" do
|
|
596
642
|
expect{subject_with_denies.title}.to raise_error(NoMethodError)
|
|
597
643
|
end
|
|
598
644
|
end
|
|
@@ -602,20 +648,20 @@ describe Draper::Base do
|
|
|
602
648
|
|
|
603
649
|
let(:subject_with_multiple_allows){ DecoratorWithMultipleAllows.new(source) }
|
|
604
650
|
|
|
605
|
-
it "
|
|
651
|
+
it "echo the allowed method" do
|
|
606
652
|
subject_with_allows.should respond_to(:goodnight_moon)
|
|
607
653
|
end
|
|
608
654
|
|
|
609
|
-
it "
|
|
655
|
+
it "echo _only_ the allowed method" do
|
|
610
656
|
subject_with_allows.should_not respond_to(:hello_world)
|
|
611
657
|
end
|
|
612
658
|
|
|
613
|
-
it "
|
|
659
|
+
it "echo the combined allowed methods" do
|
|
614
660
|
subject_with_multiple_allows.should respond_to(:goodnight_moon)
|
|
615
661
|
subject_with_multiple_allows.should respond_to(:hello_world)
|
|
616
662
|
end
|
|
617
663
|
|
|
618
|
-
it "
|
|
664
|
+
it "echo _only_ the combined allowed methods" do
|
|
619
665
|
subject_with_multiple_allows.should_not respond_to(:title)
|
|
620
666
|
end
|
|
621
667
|
end
|
|
@@ -647,62 +693,134 @@ describe Draper::Base do
|
|
|
647
693
|
end
|
|
648
694
|
}
|
|
649
695
|
|
|
650
|
-
it "
|
|
651
|
-
expect {blank_allows}.
|
|
696
|
+
it "raise an exception for a blank allows" do
|
|
697
|
+
expect {blank_allows}.to raise_error(ArgumentError)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
it "raise an exception for a blank denies" do
|
|
701
|
+
expect {blank_denies}.to raise_error(ArgumentError)
|
|
702
|
+
end
|
|
703
|
+
|
|
704
|
+
it "raise an exception for calling allows then denies" do
|
|
705
|
+
expect {using_allows_then_denies}.to raise_error(ArgumentError)
|
|
706
|
+
end
|
|
707
|
+
|
|
708
|
+
it "raise an exception for calling denies then allows" do
|
|
709
|
+
expect {using_denies_then_allows}.to raise_error(ArgumentError)
|
|
710
|
+
end
|
|
711
|
+
end
|
|
712
|
+
|
|
713
|
+
describe "a sample usage with denies_all" do
|
|
714
|
+
let(:subject_with_denies_all){ DecoratorWithDeniesAll.new(source) }
|
|
715
|
+
|
|
716
|
+
[:goodnight_moon, :hello_world, :title].each do |method|
|
|
717
|
+
it "does echo #{method} method" do
|
|
718
|
+
subject_with_denies_all.should_not respond_to(method)
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
let(:using_denies_all_then_denies_all) {
|
|
723
|
+
class DecoratorWithDeniesAllAndDeniesAll < Draper::Base
|
|
724
|
+
denies_all
|
|
725
|
+
denies_all
|
|
726
|
+
end
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
it "allows multple calls to .denies_all" do
|
|
730
|
+
expect { using_denies_all_then_denies_all }.to_not raise_error(ArgumentError)
|
|
652
731
|
end
|
|
732
|
+
end
|
|
653
733
|
|
|
654
|
-
|
|
655
|
-
|
|
734
|
+
describe "invalid usages of denies_all" do
|
|
735
|
+
let(:using_allows_then_denies_all) {
|
|
736
|
+
class DecoratorWithAllowsAndDeniesAll < Draper::Base
|
|
737
|
+
allows :hello_world
|
|
738
|
+
denies_all
|
|
739
|
+
end
|
|
740
|
+
}
|
|
741
|
+
let(:using_denies_then_denies_all) {
|
|
742
|
+
class DecoratorWithDeniesAndDeniesAll < Draper::Base
|
|
743
|
+
denies :goodnight_moon
|
|
744
|
+
denies_all
|
|
745
|
+
end
|
|
746
|
+
}
|
|
747
|
+
let(:using_denies_all_then_allows) {
|
|
748
|
+
class DecoratorWithDeniesAllAndAllows < Draper::Base
|
|
749
|
+
denies_all
|
|
750
|
+
allows :hello_world
|
|
751
|
+
end
|
|
752
|
+
}
|
|
753
|
+
let(:using_denies_all_then_denies) {
|
|
754
|
+
class DecoratorWithDeniesAllAndDenies < Draper::Base
|
|
755
|
+
denies_all
|
|
756
|
+
denies :goodnight_moon
|
|
757
|
+
end
|
|
758
|
+
}
|
|
759
|
+
it "raises an exception when calling allows then denies_all" do
|
|
760
|
+
expect {using_allows_then_denies_all}.to raise_error(ArgumentError)
|
|
656
761
|
end
|
|
657
762
|
|
|
658
|
-
it "
|
|
659
|
-
expect {
|
|
763
|
+
it "raises an exception when calling denies then denies_all" do
|
|
764
|
+
expect {using_denies_then_denies_all}.to raise_error(ArgumentError)
|
|
660
765
|
end
|
|
661
766
|
|
|
662
|
-
it "
|
|
663
|
-
expect {
|
|
767
|
+
it "raises an exception when calling denies_all then allows" do
|
|
768
|
+
expect {using_denies_all_then_allows}.to raise_error(ArgumentError)
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
it "raises an exception when calling denies_all then denies" do
|
|
772
|
+
expect {using_denies_all_then_denies}.to raise_error(ArgumentError)
|
|
664
773
|
end
|
|
665
774
|
end
|
|
666
775
|
|
|
667
776
|
context "in a Rails application" do
|
|
668
777
|
let(:decorator){ DecoratorWithApplicationHelper.decorate(Object.new) }
|
|
669
778
|
|
|
670
|
-
it "
|
|
779
|
+
it "have access to ApplicationHelper helpers" do
|
|
671
780
|
decorator.uses_hello_world == "Hello, World!"
|
|
672
781
|
end
|
|
673
782
|
|
|
674
|
-
it "
|
|
783
|
+
it "is able to use the content_tag helper" do
|
|
675
784
|
decorator.sample_content.to_s.should == "<span>Hello, World!</span>"
|
|
676
785
|
end
|
|
677
786
|
|
|
678
|
-
it "
|
|
787
|
+
it "is able to use the link_to helper" do
|
|
679
788
|
decorator.sample_link.should == "<a href=\"/World\">Hello</a>"
|
|
680
789
|
end
|
|
681
790
|
|
|
682
|
-
it "
|
|
791
|
+
it "is able to use the pluralize helper" do
|
|
683
792
|
decorator.sample_truncate.should == "Once..."
|
|
684
793
|
end
|
|
685
794
|
|
|
686
|
-
it "
|
|
795
|
+
it "is able to use l rather than helpers.l" do
|
|
687
796
|
now = Time.now
|
|
688
|
-
decorator.helpers.should_receive(:localize).with(now)
|
|
797
|
+
decorator.helpers.instance_variable_get(:@helpers).should_receive(:localize).with(now)
|
|
689
798
|
decorator.l now
|
|
690
799
|
end
|
|
800
|
+
|
|
801
|
+
it "is able to access html_escape, a private method" do
|
|
802
|
+
decorator.sample_html_escaped_text.should == '<script>danger</script>'
|
|
803
|
+
end
|
|
691
804
|
end
|
|
692
805
|
|
|
693
|
-
|
|
694
|
-
context "
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
806
|
+
context "#method_missing" do
|
|
807
|
+
context "with an isolated decorator class" do
|
|
808
|
+
let(:decorator_class) { Class.new(Decorator) }
|
|
809
|
+
subject{ decorator_class.new(source) }
|
|
810
|
+
|
|
811
|
+
context "when #hello_world is called again" do
|
|
812
|
+
it "proxies method directly after first hit" do
|
|
813
|
+
subject.methods.should_not include(:hello_world)
|
|
814
|
+
subject.hello_world
|
|
815
|
+
subject.methods.should include(:hello_world)
|
|
816
|
+
end
|
|
698
817
|
end
|
|
699
|
-
end
|
|
700
818
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
819
|
+
context "when #hello_world is called for the first time" do
|
|
820
|
+
it "hits method missing" do
|
|
821
|
+
subject.should_receive(:method_missing)
|
|
822
|
+
subject.hello_world
|
|
823
|
+
end
|
|
706
824
|
end
|
|
707
825
|
end
|
|
708
826
|
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
describe Draper::
|
|
3
|
+
describe Draper::ModelSupport do
|
|
4
4
|
subject { Product.new }
|
|
5
5
|
|
|
6
6
|
describe '#decorator' do
|
|
7
7
|
its(:decorator) { should be_kind_of(ProductDecorator) }
|
|
8
8
|
its(:decorator) { should be(subject.decorator) }
|
|
9
9
|
|
|
10
|
-
it '
|
|
10
|
+
it 'have abillity to pass block' do
|
|
11
11
|
a = Product.new.decorator { |d| d.awesome_title }
|
|
12
12
|
a.should eql "Awesome Title"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
it '
|
|
15
|
+
it 'is aliased to .decorate' do
|
|
16
16
|
subject.decorator.model.should == subject.decorate.model
|
|
17
17
|
end
|
|
18
18
|
end
|
|
@@ -23,12 +23,12 @@ describe Draper::ActiveModelSupport do
|
|
|
23
23
|
|
|
24
24
|
its(:decorate) { should be_kind_of(Draper::DecoratedEnumerableProxy) }
|
|
25
25
|
|
|
26
|
-
it "
|
|
26
|
+
it "decorate the collection" do
|
|
27
27
|
subject.decorate.size.should == 1
|
|
28
28
|
subject.decorate.to_ary[0].model.should be_a(klass)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
it "
|
|
31
|
+
it "return a new instance each time it is called" do
|
|
32
32
|
subject.decorate.should_not == subject.decorate
|
|
33
33
|
end
|
|
34
34
|
end
|