draper 4.0.2 → 4.0.5
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.
- checksums.yaml +4 -4
- data/.rspec +1 -2
- data/CHANGELOG.md +24 -0
- data/README.md +26 -7
- data/lib/draper/automatic_delegation.rb +14 -4
- data/lib/draper/collection_decorator.rb +0 -6
- data/lib/draper/compatibility/broadcastable.rb +24 -0
- data/lib/draper/compatibility/global_id.rb +9 -5
- data/lib/draper/decoratable/collection_proxy.rb +15 -0
- data/lib/draper/decoratable.rb +7 -2
- data/lib/draper/decorator.rb +2 -18
- data/lib/draper/query_methods.rb +1 -1
- data/lib/draper/railtie.rb +14 -5
- data/lib/draper/version.rb +1 -1
- data/lib/draper/view_context/build_strategy.rb +1 -9
- data/lib/draper.rb +0 -6
- metadata +16 -235
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -24
- data/.github/workflows/ci.yml +0 -55
- data/.gitignore +0 -18
- data/Gemfile +0 -24
- data/bin/bundle +0 -114
- data/bin/rake +0 -29
- data/draper.gemspec +0 -34
- data/spec/draper/collection_decorator_spec.rb +0 -291
- data/spec/draper/configuration_spec.rb +0 -49
- data/spec/draper/decoratable/equality_spec.rb +0 -10
- data/spec/draper/decoratable_spec.rb +0 -235
- data/spec/draper/decorated_association_spec.rb +0 -82
- data/spec/draper/decorates_assigned_spec.rb +0 -71
- data/spec/draper/decorator_spec.rb +0 -872
- data/spec/draper/draper_spec.rb +0 -25
- data/spec/draper/factory_spec.rb +0 -247
- data/spec/draper/finders_spec.rb +0 -166
- data/spec/draper/helper_proxy_spec.rb +0 -61
- data/spec/draper/lazy_helpers_spec.rb +0 -21
- data/spec/draper/query_methods/load_strategy_spec.rb +0 -26
- data/spec/draper/query_methods_spec.rb +0 -70
- data/spec/draper/undecorate_chain_spec.rb +0 -20
- data/spec/draper/undecorate_spec.rb +0 -19
- data/spec/draper/view_context/build_strategy_spec.rb +0 -132
- data/spec/draper/view_context_spec.rb +0 -182
- data/spec/draper/view_helpers_spec.rb +0 -8
- data/spec/dummy/.rspec +0 -2
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/assets/config/manifest.js +0 -3
- data/spec/dummy/app/controllers/application_controller.rb +0 -2
- data/spec/dummy/app/controllers/base_controller.rb +0 -4
- data/spec/dummy/app/controllers/localized_urls.rb +0 -5
- data/spec/dummy/app/controllers/posts_controller.rb +0 -20
- data/spec/dummy/app/decorators/mongoid_post_decorator.rb +0 -4
- data/spec/dummy/app/decorators/post_decorator.rb +0 -60
- data/spec/dummy/app/helpers/application_helper.rb +0 -5
- data/spec/dummy/app/jobs/publish_post_job.rb +0 -7
- data/spec/dummy/app/mailers/application_mailer.rb +0 -3
- data/spec/dummy/app/mailers/post_mailer.rb +0 -19
- data/spec/dummy/app/models/admin.rb +0 -5
- data/spec/dummy/app/models/application_record.rb +0 -3
- data/spec/dummy/app/models/mongoid_post.rb +0 -5
- data/spec/dummy/app/models/post.rb +0 -3
- data/spec/dummy/app/models/user.rb +0 -5
- data/spec/dummy/app/views/layouts/application.html.erb +0 -11
- data/spec/dummy/app/views/post_mailer/decorated_email.html.erb +0 -1
- data/spec/dummy/app/views/posts/_post.html.erb +0 -42
- data/spec/dummy/app/views/posts/show.html.erb +0 -1
- data/spec/dummy/bin/rails +0 -4
- data/spec/dummy/config/application.rb +0 -68
- data/spec/dummy/config/boot.rb +0 -5
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -35
- data/spec/dummy/config/environments/production.rb +0 -59
- data/spec/dummy/config/environments/test.rb +0 -35
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/draper.rb +0 -3
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/spec/dummy/config/initializers/inflections.rb +0 -15
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -8
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/mongoid.yml +0 -142
- data/spec/dummy/config/routes.rb +0 -9
- data/spec/dummy/config/storage.yml +0 -7
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20121019115657_create_posts.rb +0 -8
- data/spec/dummy/db/schema.rb +0 -21
- data/spec/dummy/db/seeds.rb +0 -2
- data/spec/dummy/fast_spec/post_decorator_spec.rb +0 -37
- data/spec/dummy/lib/tasks/test.rake +0 -16
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -25
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/dummy/spec/decorators/active_model_serializers_spec.rb +0 -12
- data/spec/dummy/spec/decorators/devise_spec.rb +0 -55
- data/spec/dummy/spec/decorators/helpers_spec.rb +0 -21
- data/spec/dummy/spec/decorators/post_decorator_spec.rb +0 -64
- data/spec/dummy/spec/decorators/spec_type_spec.rb +0 -7
- data/spec/dummy/spec/decorators/view_context_spec.rb +0 -22
- data/spec/dummy/spec/jobs/publish_post_job_spec.rb +0 -9
- data/spec/dummy/spec/mailers/post_mailer_spec.rb +0 -25
- data/spec/dummy/spec/models/application_spec.rb +0 -7
- data/spec/dummy/spec/models/mongoid_post_spec.rb +0 -8
- data/spec/dummy/spec/models/post_spec.rb +0 -15
- data/spec/dummy/spec/shared_examples/decoratable.rb +0 -22
- data/spec/dummy/spec/spec_helper.rb +0 -8
- data/spec/dummy/test/decorators/minitest/devise_test.rb +0 -55
- data/spec/dummy/test/decorators/minitest/helpers_test.rb +0 -21
- data/spec/dummy/test/decorators/minitest/spec_type_test.rb +0 -52
- data/spec/dummy/test/decorators/minitest/view_context_test.rb +0 -24
- data/spec/dummy/test/decorators/test_unit/devise_test.rb +0 -55
- data/spec/dummy/test/decorators/test_unit/helpers_test.rb +0 -21
- data/spec/dummy/test/decorators/test_unit/view_context_test.rb +0 -24
- data/spec/dummy/test/minitest_helper.rb +0 -2
- data/spec/dummy/test/test_helper.rb +0 -3
- data/spec/generators/controller/controller_generator_spec.rb +0 -23
- data/spec/generators/decorator/decorator_generator_spec.rb +0 -93
- data/spec/generators/install/install_generator_spec.rb +0 -19
- data/spec/integration/integration_spec.rb +0 -70
- data/spec/performance/active_record.rb +0 -4
- data/spec/performance/benchmark.rb +0 -55
- data/spec/performance/decorators.rb +0 -45
- data/spec/performance/models.rb +0 -20
- data/spec/spec_helper.rb +0 -50
- data/spec/support/dummy_app.rb +0 -85
- data/spec/support/matchers/have_text.rb +0 -50
- data/spec/support/shared_examples/decoratable_equality.rb +0 -40
- data/spec/support/shared_examples/view_helpers.rb +0 -39
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'support/shared_examples/view_helpers'
|
|
3
|
-
|
|
4
|
-
module Draper
|
|
5
|
-
describe CollectionDecorator do
|
|
6
|
-
it_behaves_like "view helpers", CollectionDecorator.new([])
|
|
7
|
-
|
|
8
|
-
describe "#initialize" do
|
|
9
|
-
describe "options validation" do
|
|
10
|
-
it "does not raise error on valid options" do
|
|
11
|
-
valid_options = {with: Decorator, context: {}}
|
|
12
|
-
expect{CollectionDecorator.new([], valid_options)}.not_to raise_error
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it "raises error on invalid options" do
|
|
16
|
-
expect{CollectionDecorator.new([], foo: "bar")}.to raise_error ArgumentError, /Unknown key/
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
context "with context" do
|
|
22
|
-
it "stores the context itself" do
|
|
23
|
-
context = {some: "context"}
|
|
24
|
-
decorator = CollectionDecorator.new([], context: context)
|
|
25
|
-
|
|
26
|
-
expect(decorator.context).to be context
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it "passes context to the individual decorators" do
|
|
30
|
-
context = {some: "context"}
|
|
31
|
-
decorator = CollectionDecorator.new([Product.new, Product.new], context: context)
|
|
32
|
-
|
|
33
|
-
decorator.each do |item|
|
|
34
|
-
expect(item.context).to be context
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
describe "#context=" do
|
|
40
|
-
it "updates the stored context" do
|
|
41
|
-
decorator = CollectionDecorator.new([], context: {some: "context"})
|
|
42
|
-
new_context = {other: "context"}
|
|
43
|
-
|
|
44
|
-
decorator.context = new_context
|
|
45
|
-
expect(decorator.context).to be new_context
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
context "when the collection is already decorated" do
|
|
49
|
-
it "updates the items' context" do
|
|
50
|
-
decorator = CollectionDecorator.new([Product.new, Product.new], context: {some: "context"})
|
|
51
|
-
decorator.decorated_collection # trigger decoration
|
|
52
|
-
new_context = {other: "context"}
|
|
53
|
-
|
|
54
|
-
decorator.context = new_context
|
|
55
|
-
decorator.each do |item|
|
|
56
|
-
expect(item.context).to be new_context
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
context "when the collection has not yet been decorated" do
|
|
62
|
-
it "does not trigger decoration" do
|
|
63
|
-
decorated = CollectionDecorator.new([]).tap(&:to_a)
|
|
64
|
-
undecorated = CollectionDecorator.new([])
|
|
65
|
-
|
|
66
|
-
expect(decorated.instance_variable_defined?(:@decorated_collection)).to be_truthy
|
|
67
|
-
expect(undecorated.instance_variable_defined?(:@decorated_collection)).to be_falsy
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
it "sets context after decoration is triggered" do
|
|
71
|
-
decorator = CollectionDecorator.new([Product.new, Product.new], context: {some: "context"})
|
|
72
|
-
new_context = {other: "context"}
|
|
73
|
-
|
|
74
|
-
decorator.context = new_context
|
|
75
|
-
decorator.each do |item|
|
|
76
|
-
expect(item.context).to be new_context
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
describe "item decoration" do
|
|
83
|
-
it "sets decorated items' source models" do
|
|
84
|
-
collection = [Product.new, Product.new]
|
|
85
|
-
decorator = CollectionDecorator.new(collection)
|
|
86
|
-
|
|
87
|
-
decorator.zip collection do |item, object|
|
|
88
|
-
expect(item.object).to be object
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
context "when the :with option was given" do
|
|
93
|
-
it "uses the :with option" do
|
|
94
|
-
decorator = CollectionDecorator.new([Product.new], with: OtherDecorator).first
|
|
95
|
-
|
|
96
|
-
expect(decorator).to be_decorated_with OtherDecorator
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
context "when the :with option was not given" do
|
|
101
|
-
it "infers the item decorator from each item" do
|
|
102
|
-
decorator = CollectionDecorator.new([double(decorate: :inferred_decorator)]).first
|
|
103
|
-
|
|
104
|
-
expect(decorator).to be :inferred_decorator
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
describe ".delegate" do
|
|
110
|
-
protect_class ProductsDecorator
|
|
111
|
-
|
|
112
|
-
it "defaults the :to option to :object" do
|
|
113
|
-
expect(Object).to receive(:delegate).with(:foo, :bar, to: :object)
|
|
114
|
-
ProductsDecorator.delegate :foo, :bar
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
it "does not overwrite the :to option if supplied" do
|
|
118
|
-
expect(Object).to receive(:delegate).with(:foo, :bar, to: :baz)
|
|
119
|
-
ProductsDecorator.delegate :foo, :bar, to: :baz
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
describe "#find" do
|
|
124
|
-
it "decorates Enumerable#find" do
|
|
125
|
-
decorator = CollectionDecorator.new([])
|
|
126
|
-
|
|
127
|
-
expect(decorator.decorated_collection).to receive(:find).and_return(:delegated)
|
|
128
|
-
expect(decorator.find{|p| p.title == "title"}).to be :delegated
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
describe "#to_ary" do
|
|
133
|
-
# required for `render @collection` in Rails
|
|
134
|
-
it "delegates to the decorated collection" do
|
|
135
|
-
decorator = CollectionDecorator.new([])
|
|
136
|
-
|
|
137
|
-
expect(decorator.decorated_collection).to receive(:to_ary).and_return(:delegated)
|
|
138
|
-
expect(decorator.to_ary).to be :delegated
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
it "delegates array methods to the decorated collection" do
|
|
143
|
-
decorator = CollectionDecorator.new([])
|
|
144
|
-
|
|
145
|
-
allow(decorator).to receive_message_chain(:decorated_collection, :[]).with(42).and_return(:delegated)
|
|
146
|
-
expect(decorator[42]).to be :delegated
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
describe "#==" do
|
|
150
|
-
context "when comparing to a collection decorator with the same object" do
|
|
151
|
-
it "returns true" do
|
|
152
|
-
object = [Product.new, Product.new]
|
|
153
|
-
decorator = CollectionDecorator.new(object)
|
|
154
|
-
other = ProductsDecorator.new(object)
|
|
155
|
-
|
|
156
|
-
expect(decorator == other).to be_truthy
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
context "when comparing to a collection decorator with a different object" do
|
|
161
|
-
it "returns false" do
|
|
162
|
-
decorator = CollectionDecorator.new([Product.new, Product.new])
|
|
163
|
-
other = ProductsDecorator.new([Product.new, Product.new])
|
|
164
|
-
|
|
165
|
-
expect(decorator == other).to be_falsey
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
context "when comparing to a collection of the same items" do
|
|
170
|
-
it "returns true" do
|
|
171
|
-
object = [Product.new, Product.new]
|
|
172
|
-
decorator = CollectionDecorator.new(object)
|
|
173
|
-
other = object.dup
|
|
174
|
-
|
|
175
|
-
expect(decorator == other).to be_truthy
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
context "when comparing to a collection of different items" do
|
|
180
|
-
it "returns false" do
|
|
181
|
-
decorator = CollectionDecorator.new([Product.new, Product.new])
|
|
182
|
-
other = [Product.new, Product.new]
|
|
183
|
-
|
|
184
|
-
expect(decorator == other).to be_falsey
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
context "when the decorated collection has been modified" do
|
|
189
|
-
it "is no longer equal to the object" do
|
|
190
|
-
object = [Product.new, Product.new]
|
|
191
|
-
decorator = CollectionDecorator.new(object)
|
|
192
|
-
other = object.dup
|
|
193
|
-
|
|
194
|
-
decorator << Product.new.decorate
|
|
195
|
-
expect(decorator == other).to be_falsey
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
describe "#to_s" do
|
|
201
|
-
context "when :with option was given" do
|
|
202
|
-
it "returns a string representation of the collection decorator" do
|
|
203
|
-
decorator = CollectionDecorator.new(["a", "b", "c"], with: ProductDecorator)
|
|
204
|
-
|
|
205
|
-
expect(decorator.to_s).to eq '#<Draper::CollectionDecorator of ProductDecorator for ["a", "b", "c"]>'
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
context "when :with option was not given" do
|
|
210
|
-
it "returns a string representation of the collection decorator" do
|
|
211
|
-
decorator = CollectionDecorator.new(["a", "b", "c"])
|
|
212
|
-
|
|
213
|
-
expect(decorator.to_s).to eq '#<Draper::CollectionDecorator of inferred decorators for ["a", "b", "c"]>'
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
context "for a custom subclass" do
|
|
218
|
-
it "uses the custom class name" do
|
|
219
|
-
decorator = ProductsDecorator.new([])
|
|
220
|
-
|
|
221
|
-
expect(decorator.to_s).to match(/ProductsDecorator/)
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
end
|
|
225
|
-
|
|
226
|
-
describe '#object' do
|
|
227
|
-
it 'returns the underlying collection' do
|
|
228
|
-
collection = [Product.new]
|
|
229
|
-
decorator = ProductsDecorator.new(collection)
|
|
230
|
-
|
|
231
|
-
expect(decorator.object).to eq collection
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
describe '#decorated?' do
|
|
236
|
-
it 'returns true' do
|
|
237
|
-
decorator = ProductsDecorator.new([Product.new])
|
|
238
|
-
|
|
239
|
-
expect(decorator).to be_decorated
|
|
240
|
-
end
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
describe '#decorated_with?' do
|
|
244
|
-
it "checks if a decorator has been applied to a collection" do
|
|
245
|
-
decorator = ProductsDecorator.new([Product.new])
|
|
246
|
-
|
|
247
|
-
expect(decorator).to be_decorated_with ProductsDecorator
|
|
248
|
-
expect(decorator).not_to be_decorated_with OtherDecorator
|
|
249
|
-
end
|
|
250
|
-
end
|
|
251
|
-
|
|
252
|
-
describe '#kind_of?' do
|
|
253
|
-
it 'asks the kind of its decorated collection' do
|
|
254
|
-
decorator = ProductsDecorator.new([])
|
|
255
|
-
expect(decorator.decorated_collection).to receive(:kind_of?).with(Array).and_return("true")
|
|
256
|
-
expect(decorator.kind_of?(Array)).to eq "true"
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
context 'when asking the underlying collection returns false' do
|
|
260
|
-
it 'asks the CollectionDecorator instance itself' do
|
|
261
|
-
decorator = ProductsDecorator.new([])
|
|
262
|
-
allow(decorator.decorated_collection).to receive(:kind_of?).with(::Draper::CollectionDecorator).and_return(false)
|
|
263
|
-
expect(decorator.kind_of?(::Draper::CollectionDecorator)).to be true
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
describe '#is_a?' do
|
|
269
|
-
it 'aliases to #kind_of?' do
|
|
270
|
-
decorator = ProductsDecorator.new([])
|
|
271
|
-
expect(decorator.method(:kind_of?)).to eq decorator.method(:is_a?)
|
|
272
|
-
end
|
|
273
|
-
end
|
|
274
|
-
|
|
275
|
-
describe "#replace" do
|
|
276
|
-
it "replaces the decorated collection" do
|
|
277
|
-
decorator = CollectionDecorator.new([Product.new])
|
|
278
|
-
replacement = [:foo, :bar]
|
|
279
|
-
|
|
280
|
-
decorator.replace replacement
|
|
281
|
-
expect(decorator).to match_array replacement
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
it "returns itself" do
|
|
285
|
-
decorator = CollectionDecorator.new([Product.new])
|
|
286
|
-
|
|
287
|
-
expect(decorator.replace([:foo, :bar])).to be decorator
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
end
|
|
291
|
-
end
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
module Draper
|
|
4
|
-
RSpec.describe Configuration do
|
|
5
|
-
it 'yields Draper on configure' do
|
|
6
|
-
Draper.configure { |config| expect(config).to be Draper }
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
describe '#default_controller' do
|
|
10
|
-
it 'defaults default_controller to ApplicationController' do
|
|
11
|
-
expect(Draper.default_controller).to be ApplicationController
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it 'allows customizing default_controller through configure' do
|
|
15
|
-
default = Draper.default_controller
|
|
16
|
-
|
|
17
|
-
Draper.configure do |config|
|
|
18
|
-
config.default_controller = CustomController
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
expect(Draper.default_controller).to be CustomController
|
|
22
|
-
|
|
23
|
-
Draper.default_controller = default
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
describe '#default_query_methods_strategy' do
|
|
28
|
-
let!(:default) { Draper.default_query_methods_strategy }
|
|
29
|
-
|
|
30
|
-
subject { Draper.default_query_methods_strategy }
|
|
31
|
-
|
|
32
|
-
context 'when there is no custom strategy' do
|
|
33
|
-
it { is_expected.to eq(:active_record) }
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
context 'when using a custom strategy' do
|
|
37
|
-
before do
|
|
38
|
-
Draper.configure do |config|
|
|
39
|
-
config.default_query_methods_strategy = :mongoid
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
after { Draper.default_query_methods_strategy = default }
|
|
44
|
-
|
|
45
|
-
it { is_expected.to eq(:mongoid) }
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'support/shared_examples/decoratable_equality'
|
|
3
|
-
|
|
4
|
-
module Draper
|
|
5
|
-
describe Decoratable do
|
|
6
|
-
describe "#decorate" do
|
|
7
|
-
it "returns a decorator for self" do
|
|
8
|
-
product = Product.new
|
|
9
|
-
decorator = product.decorate
|
|
10
|
-
|
|
11
|
-
expect(decorator).to be_a ProductDecorator
|
|
12
|
-
expect(decorator.object).to be product
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it "accepts context" do
|
|
16
|
-
context = {some: "context"}
|
|
17
|
-
decorator = Product.new.decorate(context: context)
|
|
18
|
-
|
|
19
|
-
expect(decorator.context).to be context
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it "uses the #decorator_class" do
|
|
23
|
-
product = Product.new
|
|
24
|
-
allow(product).to receive_messages decorator_class: OtherDecorator
|
|
25
|
-
|
|
26
|
-
expect(product.decorate).to be_an_instance_of OtherDecorator
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
describe "#applied_decorators" do
|
|
31
|
-
it "returns an empty list" do
|
|
32
|
-
expect(Product.new.applied_decorators).to eq []
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
describe "#decorated_with?" do
|
|
37
|
-
it "returns false" do
|
|
38
|
-
expect(Product.new).not_to be_decorated_with Decorator
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
describe "#decorated?" do
|
|
43
|
-
it "returns false" do
|
|
44
|
-
expect(Product.new).not_to be_decorated
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
describe "#decorator_class?" do
|
|
49
|
-
it "returns true for decoratable model" do
|
|
50
|
-
expect(Product.new.decorator_class?).to be_truthy
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
it "returns false for non-decoratable model" do
|
|
54
|
-
expect(Model.new.decorator_class?).to be_falsey
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
describe ".decorator_class?" do
|
|
59
|
-
it "returns true for decoratable model" do
|
|
60
|
-
expect(Product.decorator_class?).to be_truthy
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it "returns false for non-decoratable model" do
|
|
64
|
-
expect(Model.decorator_class?).to be_falsey
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
describe "#decorator_class" do
|
|
69
|
-
it "delegates to .decorator_class" do
|
|
70
|
-
product = Product.new
|
|
71
|
-
|
|
72
|
-
expect(Product).to receive(:decorator_class).and_return(:some_decorator)
|
|
73
|
-
expect(product.decorator_class).to be :some_decorator
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "specifies the class that #decorator_class was first called on (superclass)" do
|
|
77
|
-
person = Person.new
|
|
78
|
-
expect { person.decorator_class }.to raise_error(Draper::UninferrableDecoratorError, 'Could not infer a decorator for Person.')
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it "specifies the class that #decorator_class was first called on (subclass)" do
|
|
82
|
-
child = Child.new
|
|
83
|
-
expect { child.decorator_class }.to raise_error(Draper::UninferrableDecoratorError, 'Could not infer a decorator for Child.')
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
describe "#==" do
|
|
88
|
-
it_behaves_like "decoration-aware #==", Product.new
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
describe "#===" do
|
|
92
|
-
it "is true when #== is true" do
|
|
93
|
-
product = Product.new
|
|
94
|
-
|
|
95
|
-
expect(product).to receive(:==).and_return(true)
|
|
96
|
-
expect(product === :anything).to be_truthy
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
it "is false when #== is false" do
|
|
100
|
-
product = Product.new
|
|
101
|
-
|
|
102
|
-
expect(product).to receive(:==).and_return(false)
|
|
103
|
-
expect(product === :anything).to be_falsey
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
describe ".====" do
|
|
108
|
-
it "is true for an instance" do
|
|
109
|
-
expect(Product === Product.new).to be_truthy
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
it "is true for a derived instance" do
|
|
113
|
-
expect(Product === Class.new(Product).new).to be_truthy
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
it "is false for an unrelated instance" do
|
|
117
|
-
expect(Product === Model.new).to be_falsey
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
it "is true for a decorated instance" do
|
|
121
|
-
decorator = Product.new.decorate
|
|
122
|
-
|
|
123
|
-
expect(Product === decorator).to be_truthy
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
it "is true for a decorated derived instance" do
|
|
127
|
-
decorator = Class.new(Product).new.decorate
|
|
128
|
-
|
|
129
|
-
expect(Product === decorator).to be_truthy
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
it "is false for a decorated unrelated instance" do
|
|
133
|
-
decorator = Other.new.decorate
|
|
134
|
-
|
|
135
|
-
expect(Product === decorator).to be_falsey
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
it "is false for a non-decorator which happens to respond to object" do
|
|
139
|
-
decorator = double(object: Product.new)
|
|
140
|
-
|
|
141
|
-
expect(Product === decorator).to be_falsey
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
describe ".decorate" do
|
|
146
|
-
it "calls #decorate_collection on .decorator_class" do
|
|
147
|
-
scoped = [Product.new]
|
|
148
|
-
allow(Product).to receive(:all).and_return(scoped)
|
|
149
|
-
|
|
150
|
-
expect(Product.decorator_class).to receive(:decorate_collection).with(scoped, with: nil).and_return(:decorated_collection)
|
|
151
|
-
expect(Product.decorate).to be :decorated_collection
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
it "accepts options" do
|
|
155
|
-
options = {with: ProductDecorator, context: {some: "context"}}
|
|
156
|
-
allow(Product).to receive(:all).and_return([])
|
|
157
|
-
|
|
158
|
-
expect(Product.decorator_class).to receive(:decorate_collection).with([], options)
|
|
159
|
-
Product.decorate(options)
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
describe ".decorator_class" do
|
|
164
|
-
context "for classes" do
|
|
165
|
-
it "infers the decorator from the class" do
|
|
166
|
-
expect(Product.decorator_class).to be ProductDecorator
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
context "without a decorator on its own" do
|
|
170
|
-
it "infers the decorator from a superclass" do
|
|
171
|
-
expect(SpecialProduct.decorator_class).to be ProductDecorator
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
context "for ActiveModel classes" do
|
|
177
|
-
it "infers the decorator from the model name" do
|
|
178
|
-
allow(Product).to receive(:model_name){"Other"}
|
|
179
|
-
|
|
180
|
-
expect(Product.decorator_class).to be OtherDecorator
|
|
181
|
-
end
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
context "in a namespace" do
|
|
185
|
-
context "for classes" do
|
|
186
|
-
it "infers the decorator from the class" do
|
|
187
|
-
expect(Namespaced::Product.decorator_class).to be Namespaced::ProductDecorator
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
context "for ActiveModel classes" do
|
|
192
|
-
it "infers the decorator from the model name" do
|
|
193
|
-
allow(Namespaced::Product).to receive(:model_name).and_return("Namespaced::Other")
|
|
194
|
-
|
|
195
|
-
expect(Namespaced::Product.decorator_class).to be Namespaced::OtherDecorator
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
context "when the decorator contains name error" do
|
|
201
|
-
it "throws an NameError" do
|
|
202
|
-
# We imitate ActiveSupport::Autoload behavior here in order to cause lazy NameError exception raising
|
|
203
|
-
allow_any_instance_of(Module).to receive(:const_missing) { Class.new { any_nonexisting_method_name } }
|
|
204
|
-
|
|
205
|
-
expect{Model.decorator_class}.to raise_error { |error| expect(error).to be_an_instance_of(NameError) }
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
context "when the decorator can't be inferred" do
|
|
210
|
-
it "throws an UninferrableDecoratorError" do
|
|
211
|
-
expect{Model.decorator_class}.to raise_error UninferrableDecoratorError
|
|
212
|
-
end
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
context "when an unrelated NameError is thrown" do
|
|
216
|
-
it "re-raises that error" do
|
|
217
|
-
# Not related to safe_constantize behavior, we just want to raise a NameError inside the function
|
|
218
|
-
allow_any_instance_of(String).to receive(:safe_constantize) { Draper::Base }
|
|
219
|
-
expect{Product.decorator_class}.to raise_error NameError, /Draper::Base/
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
context "when an anonymous class is given" do
|
|
224
|
-
it "infers the decorator from a superclass" do
|
|
225
|
-
anonymous_class = Class.new(Product) do
|
|
226
|
-
def self.name
|
|
227
|
-
to_s
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
expect(anonymous_class.decorator_class).to be ProductDecorator
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
module Draper
|
|
4
|
-
describe DecoratedAssociation do
|
|
5
|
-
describe "#initialize" do
|
|
6
|
-
it "accepts valid options" do
|
|
7
|
-
valid_options = {with: Decorator, scope: :foo, context: {}}
|
|
8
|
-
expect{DecoratedAssociation.new(Decorator.new(Model.new), :association, valid_options)}.not_to raise_error
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it "rejects invalid options" do
|
|
12
|
-
expect{DecoratedAssociation.new(Decorator.new(Model.new), :association, foo: "bar")}.to raise_error ArgumentError, /Unknown key/
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it "creates a factory" do
|
|
16
|
-
options = {with: Decorator, context: {foo: "bar"}}
|
|
17
|
-
|
|
18
|
-
expect(Factory).to receive(:new).with(options)
|
|
19
|
-
DecoratedAssociation.new(double, :association, options)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
describe ":with option" do
|
|
23
|
-
it "defaults to nil" do
|
|
24
|
-
expect(Factory).to receive(:new).with(with: nil, context: anything())
|
|
25
|
-
DecoratedAssociation.new(double, :association, {})
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
describe ":context option" do
|
|
30
|
-
it "defaults to the identity function" do
|
|
31
|
-
expect(Factory).to receive(:new) do |options|
|
|
32
|
-
options[:context].call(:anything) == :anything
|
|
33
|
-
end
|
|
34
|
-
DecoratedAssociation.new(double, :association, {})
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
describe "#call" do
|
|
40
|
-
it "calls the factory" do
|
|
41
|
-
factory = double
|
|
42
|
-
allow(Factory).to receive_messages(new: factory)
|
|
43
|
-
associated = double
|
|
44
|
-
owner_context = {foo: "bar"}
|
|
45
|
-
object = double(association: associated)
|
|
46
|
-
owner = double(object: object, context: owner_context)
|
|
47
|
-
decorated_association = DecoratedAssociation.new(owner, :association, {})
|
|
48
|
-
decorated = double
|
|
49
|
-
|
|
50
|
-
expect(factory).to receive(:decorate).with(associated, context_args: owner_context).and_return(decorated)
|
|
51
|
-
expect(decorated_association.call).to be decorated
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "memoizes" do
|
|
55
|
-
factory = double
|
|
56
|
-
allow(Factory).to receive_messages(new: factory)
|
|
57
|
-
owner = double(object: double(association: double), context: {})
|
|
58
|
-
decorated_association = DecoratedAssociation.new(owner, :association, {})
|
|
59
|
-
decorated = double
|
|
60
|
-
|
|
61
|
-
expect(factory).to receive(:decorate).once.and_return(decorated)
|
|
62
|
-
expect(decorated_association.call).to be decorated
|
|
63
|
-
expect(decorated_association.call).to be decorated
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
context "when the :scope option was given" do
|
|
67
|
-
it "applies the scope before decoration" do
|
|
68
|
-
factory = double
|
|
69
|
-
allow(Factory).to receive_messages(new: factory)
|
|
70
|
-
scoped = double
|
|
71
|
-
object = double(association: double(applied_scope: scoped))
|
|
72
|
-
owner = double(object: object, context: {})
|
|
73
|
-
decorated_association = DecoratedAssociation.new(owner, :association, scope: :applied_scope)
|
|
74
|
-
decorated = double
|
|
75
|
-
|
|
76
|
-
expect(factory).to receive(:decorate).with(scoped, anything()).and_return(decorated)
|
|
77
|
-
expect(decorated_association.call).to be decorated
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|