rails-patterns 0.3.0 → 0.7.3
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 +5 -5
- data/.github/workflows/ruby.yml +33 -0
- data/Gemfile +8 -4
- data/Gemfile.lock +104 -56
- data/README.md +183 -6
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/lib/patterns/calculation.rb +59 -0
- data/lib/patterns/form.rb +117 -0
- data/lib/patterns/query.rb +20 -15
- data/lib/patterns/service.rb +10 -6
- data/lib/rails-patterns.rb +2 -0
- data/rails-patterns.gemspec +25 -7
- data/spec/helpers/custom_calculation.rb +16 -0
- data/spec/helpers/custom_calculation_script.rb +4 -0
- data/spec/helpers/rails_redis_cache_mock.rb +5 -0
- data/spec/patterns/calculation_spec.rb +200 -0
- data/spec/patterns/form_spec.rb +478 -0
- data/spec/patterns/service_spec.rb +16 -1
- data/spec/spec_helper.rb +6 -1
- metadata +56 -6
@@ -0,0 +1,478 @@
|
|
1
|
+
RSpec.describe Patterns::Form do
|
2
|
+
after { Object.send(:remove_const, :CustomForm) if defined?(CustomForm) }
|
3
|
+
|
4
|
+
it "includes Virtus.model" do
|
5
|
+
CustomForm = Class.new(Patterns::Form)
|
6
|
+
|
7
|
+
expect(CustomForm.attribute_set).to be_kind_of(Virtus::AttributeSet)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "includes ActiveModel::Validations" do
|
11
|
+
CustomForm = Class.new(Patterns::Form)
|
12
|
+
|
13
|
+
expect(CustomForm).to be < ActiveModel::Validations
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".new" do
|
17
|
+
it "returns form instance" do
|
18
|
+
CustomForm = Class.new(Patterns::Form)
|
19
|
+
|
20
|
+
form = CustomForm.new(double)
|
21
|
+
|
22
|
+
expect(form).to be_a_kind_of(CustomForm)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "assigns form attributes with values passed as second argument" do
|
26
|
+
CustomForm = Class.new(Patterns::Form) do
|
27
|
+
attribute :first_name, String
|
28
|
+
attribute :last_name, String
|
29
|
+
end
|
30
|
+
|
31
|
+
form = CustomForm.new({ first_name: "Tony", last_name: "Stark" })
|
32
|
+
|
33
|
+
expect(form.first_name).to eq "Tony"
|
34
|
+
expect(form.last_name).to eq "Stark"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "handles both symbols and strings as attribute keys" do
|
38
|
+
CustomForm = Class.new(Patterns::Form) do
|
39
|
+
attribute :first_name, String
|
40
|
+
attribute :last_name, String
|
41
|
+
attribute :email, String
|
42
|
+
attribute :age, Integer
|
43
|
+
end
|
44
|
+
resource = double(
|
45
|
+
attributes: {
|
46
|
+
"first_name" => "Bat",
|
47
|
+
last_name: "Man",
|
48
|
+
"email" => "bat@man.dev"
|
49
|
+
}
|
50
|
+
)
|
51
|
+
|
52
|
+
form = CustomForm.new(
|
53
|
+
resource, { first_name: "Christian", "last_name" => "Bale", "age" => 40 }
|
54
|
+
)
|
55
|
+
|
56
|
+
expect(form.first_name).to eq "Christian"
|
57
|
+
expect(form.last_name).to eq "Bale"
|
58
|
+
expect(form.email).to eq "bat@man.dev"
|
59
|
+
expect(form.age).to eq 40
|
60
|
+
end
|
61
|
+
|
62
|
+
context "if second parameter is ActionController::Parameters object" do
|
63
|
+
it "treats ActionController::Parameters as regular hash" do
|
64
|
+
CustomForm = Class.new(Patterns::Form) do
|
65
|
+
attribute :first_name, String
|
66
|
+
attribute :last_name, String
|
67
|
+
end
|
68
|
+
|
69
|
+
strong_parameters = ActionController::Parameters.new(
|
70
|
+
{ "first_name" => "Kobe", "last_name" => "Bryant" }
|
71
|
+
)
|
72
|
+
|
73
|
+
form = CustomForm.new(double, strong_parameters)
|
74
|
+
|
75
|
+
expect(form.first_name).to eq "Kobe"
|
76
|
+
expect(form.last_name).to eq "Bryant"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "if only parameter is ActionController::Parameters object" do
|
81
|
+
it "treats ActionController::Parameters as regular hash" do
|
82
|
+
CustomForm = Class.new(Patterns::Form) do
|
83
|
+
attribute :first_name, String
|
84
|
+
attribute :last_name, String
|
85
|
+
end
|
86
|
+
|
87
|
+
strong_parameters = ActionController::Parameters.new(
|
88
|
+
{ "first_name" => "Saul", "last_name" => "Goodman" }
|
89
|
+
)
|
90
|
+
|
91
|
+
form = CustomForm.new(strong_parameters)
|
92
|
+
|
93
|
+
expect(form.first_name).to eq "Saul"
|
94
|
+
expect(form.last_name).to eq "Goodman"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "can be initialized without providing resource" do
|
99
|
+
CustomForm = Class.new(Patterns::Form)
|
100
|
+
|
101
|
+
form = CustomForm.new
|
102
|
+
|
103
|
+
expect(form).to be_a_kind_of(CustomForm)
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when resource exists" do
|
107
|
+
context "when resource responds to #attributes" do
|
108
|
+
it "assigns merged attributes from resource and passed as argument" do
|
109
|
+
CustomForm = Class.new(Patterns::Form) do
|
110
|
+
attribute :first_name, String
|
111
|
+
attribute :last_name, String
|
112
|
+
end
|
113
|
+
resource = double(attributes: { first_name: "Jack", last_name: "Black" })
|
114
|
+
|
115
|
+
form = CustomForm.new(resource, { first_name: "Tony" })
|
116
|
+
|
117
|
+
expect(form.first_name).to eq "Tony"
|
118
|
+
expect(form.last_name).to eq "Black"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "attempts to use public getters to populate missing attributes" do
|
122
|
+
CustomForm = Class.new(Patterns::Form) do
|
123
|
+
attribute :first_name, String
|
124
|
+
attribute :last_name, String
|
125
|
+
attribute :age, Integer
|
126
|
+
attribute :email, String
|
127
|
+
end
|
128
|
+
resource = double(attributes: { first_name: "Jack", last_name: "Black" }, age: 27)
|
129
|
+
|
130
|
+
form = CustomForm.new(resource, { first_name: "Tony" })
|
131
|
+
|
132
|
+
expect(form.first_name).to eq "Tony"
|
133
|
+
expect(form.last_name).to eq "Black"
|
134
|
+
expect(form.age).to eq 27
|
135
|
+
expect(form.email).to eq nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context "when resource does not respond to #attributes" do
|
140
|
+
it "assigns attributes passed as arguments" do
|
141
|
+
CustomForm = Class.new(Patterns::Form) do
|
142
|
+
attribute :first_name, String
|
143
|
+
attribute :last_name, String
|
144
|
+
end
|
145
|
+
|
146
|
+
form = CustomForm.new(double, { first_name: "Tony" })
|
147
|
+
|
148
|
+
expect(form.first_name).to eq "Tony"
|
149
|
+
expect(form.last_name).to eq nil
|
150
|
+
end
|
151
|
+
|
152
|
+
it "attempts to use public getters to populate missing attributes" do
|
153
|
+
CustomForm = Class.new(Patterns::Form) do
|
154
|
+
attribute :first_name, String
|
155
|
+
attribute :last_name, String
|
156
|
+
attribute :age, Integer
|
157
|
+
attribute :email, String
|
158
|
+
end
|
159
|
+
resource = double(last_name: "Black", age: 27)
|
160
|
+
|
161
|
+
form = CustomForm.new(resource, { first_name: "Tony" })
|
162
|
+
|
163
|
+
expect(form.first_name).to eq "Tony"
|
164
|
+
expect(form.last_name).to eq "Black"
|
165
|
+
expect(form.age).to eq 27
|
166
|
+
expect(form.email).to eq nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "#save" do
|
173
|
+
context "when form is valid" do
|
174
|
+
it "requires #persist method to be implemented" do
|
175
|
+
CustomForm = Class.new(Patterns::Form)
|
176
|
+
|
177
|
+
form = CustomForm.new(double)
|
178
|
+
|
179
|
+
expect { form.save }.to raise_error NotImplementedError, "#persist has to be implemented"
|
180
|
+
end
|
181
|
+
|
182
|
+
it "returns result of #persist method" do
|
183
|
+
CustomForm = Class.new(Patterns::Form) do
|
184
|
+
private
|
185
|
+
|
186
|
+
def persist
|
187
|
+
10
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
form = CustomForm.new(double)
|
192
|
+
result = form.save
|
193
|
+
|
194
|
+
expect(result).to eq 10
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context "when form is invalid" do
|
199
|
+
it "does not call #persist method" do
|
200
|
+
CustomForm = Class.new(Patterns::Form) do
|
201
|
+
private
|
202
|
+
|
203
|
+
def persist
|
204
|
+
raise StandardError, "Should not be raised!"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
form = CustomForm.new(double)
|
208
|
+
allow(form).to receive(:valid?) { false }
|
209
|
+
|
210
|
+
expect { form.save }.to_not raise_error
|
211
|
+
end
|
212
|
+
|
213
|
+
it "returns false" do
|
214
|
+
CustomForm = Class.new(Patterns::Form) do
|
215
|
+
private
|
216
|
+
|
217
|
+
def persist
|
218
|
+
10
|
219
|
+
end
|
220
|
+
end
|
221
|
+
form = CustomForm.new(double)
|
222
|
+
allow(form).to receive(:valid?) { false }
|
223
|
+
|
224
|
+
expect(form.save).to eq false
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "#save!" do
|
230
|
+
context "#save returned falsey value" do
|
231
|
+
it "returns Pattern::Form::Invalid exception" do
|
232
|
+
CustomForm = Class.new(Patterns::Form) do
|
233
|
+
private
|
234
|
+
|
235
|
+
def persist
|
236
|
+
10
|
237
|
+
end
|
238
|
+
end
|
239
|
+
form = CustomForm.new(double)
|
240
|
+
allow(form).to receive(:save) { false }
|
241
|
+
|
242
|
+
expect { form.save! }.to raise_error Patterns::Form::Invalid
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
context "#save returned truthy value" do
|
247
|
+
it "returns value returned from #save" do
|
248
|
+
CustomForm = Class.new(Patterns::Form) do
|
249
|
+
private
|
250
|
+
|
251
|
+
def persist
|
252
|
+
10
|
253
|
+
end
|
254
|
+
end
|
255
|
+
form = CustomForm.new(double)
|
256
|
+
|
257
|
+
expect(form.save!).to eq 10
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "#as" do
|
263
|
+
it "saves argument in @form_owner" do
|
264
|
+
CustomForm = Class.new(Patterns::Form)
|
265
|
+
form_owner = double("Form owner")
|
266
|
+
|
267
|
+
form = CustomForm.new(double).as(form_owner)
|
268
|
+
|
269
|
+
expect(form.instance_variable_get("@form_owner")).to eq form_owner
|
270
|
+
end
|
271
|
+
|
272
|
+
it "returns itself" do
|
273
|
+
CustomForm = Class.new(Patterns::Form)
|
274
|
+
|
275
|
+
form = CustomForm.new(double)
|
276
|
+
result = form.as(double)
|
277
|
+
|
278
|
+
expect(result).to eq form
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
describe "#persisted?" do
|
283
|
+
context "when resource is nil" do
|
284
|
+
it "returns false" do
|
285
|
+
CustomForm = Class.new(Patterns::Form)
|
286
|
+
|
287
|
+
form = CustomForm.new
|
288
|
+
|
289
|
+
expect(form.persisted?).to eq false
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "when resource is not nil" do
|
294
|
+
context "when resource responds to #persisted?" do
|
295
|
+
it "returns resource#persisted?" do
|
296
|
+
CustomForm = Class.new(Patterns::Form)
|
297
|
+
|
298
|
+
form_1 = CustomForm.new(double(persisted?: true))
|
299
|
+
form_2 = CustomForm.new(double(persisted?: false))
|
300
|
+
|
301
|
+
expect(form_1.persisted?).to eq true
|
302
|
+
expect(form_2.persisted?).to eq false
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
context "when resource does not respond to #persisted?" do
|
307
|
+
it "returns false" do
|
308
|
+
CustomForm = Class.new(Patterns::Form)
|
309
|
+
|
310
|
+
form = CustomForm.new(double)
|
311
|
+
|
312
|
+
expect(form.persisted?).to eq false
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe "#to_model" do
|
319
|
+
it "returns itself" do
|
320
|
+
CustomForm = Class.new(Patterns::Form)
|
321
|
+
|
322
|
+
form = CustomForm.new(double)
|
323
|
+
|
324
|
+
expect(form.to_model).to eq form
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
describe "#to_partial_path" do
|
329
|
+
it "returns nil" do
|
330
|
+
CustomForm = Class.new(Patterns::Form)
|
331
|
+
|
332
|
+
form = CustomForm.new(double)
|
333
|
+
|
334
|
+
expect(form.to_partial_path).to eq nil
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
describe "#to_key" do
|
339
|
+
it "returns nil" do
|
340
|
+
CustomForm = Class.new(Patterns::Form)
|
341
|
+
|
342
|
+
form = CustomForm.new(double)
|
343
|
+
|
344
|
+
expect(form.to_key).to eq nil
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe "#to_param" do
|
349
|
+
context "resource exists" do
|
350
|
+
context "resource responds to #to_param" do
|
351
|
+
it "returns resource#to_param" do
|
352
|
+
CustomForm = Class.new(Patterns::Form)
|
353
|
+
resource = double(to_param: 100)
|
354
|
+
|
355
|
+
form = CustomForm.new(resource)
|
356
|
+
|
357
|
+
expect(form.to_param).to eq 100
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context "resource does not exist" do
|
363
|
+
it "returns nil" do
|
364
|
+
CustomForm = Class.new(Patterns::Form)
|
365
|
+
|
366
|
+
form = CustomForm.new
|
367
|
+
|
368
|
+
expect(form.to_param).to eq nil
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
describe "#model_name" do
|
374
|
+
context "resource exists" do
|
375
|
+
context "resource responds to #model_name" do
|
376
|
+
context "param_key is not defined" do
|
377
|
+
it "returns object's model name param_key, route_key and singular_route_key" do
|
378
|
+
CustomForm = Class.new(Patterns::Form)
|
379
|
+
resource = double(model_name: double(
|
380
|
+
param_key: "resource_key",
|
381
|
+
route_key: "resource_keys",
|
382
|
+
singular_route_key: "resource_key"
|
383
|
+
))
|
384
|
+
|
385
|
+
form = CustomForm.new(resource)
|
386
|
+
result = form.model_name
|
387
|
+
|
388
|
+
expect(result).to have_attributes(
|
389
|
+
param_key: "resource_key",
|
390
|
+
route_key: "resource_keys",
|
391
|
+
singular_route_key: "resource_key"
|
392
|
+
)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
context "param_key is defined" do
|
397
|
+
it "returns param_key, route_key and singular_route_key derived from param key" do
|
398
|
+
CustomForm = Class.new(Patterns::Form) do
|
399
|
+
param_key "test_key"
|
400
|
+
end
|
401
|
+
resource = double(model_name: double(
|
402
|
+
param_key: "resource_key",
|
403
|
+
route_key: "resource_keys",
|
404
|
+
singular_route_key: "resource_key"
|
405
|
+
))
|
406
|
+
|
407
|
+
form = CustomForm.new(resource)
|
408
|
+
result = form.model_name
|
409
|
+
|
410
|
+
expect(result).to have_attributes(
|
411
|
+
param_key: "test_key",
|
412
|
+
route_key: "test_keys",
|
413
|
+
singular_route_key: "test_key"
|
414
|
+
)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
context "resource does not respond to #model_name" do
|
420
|
+
context "param_key is not defined" do
|
421
|
+
it "raises NoParamKey" do
|
422
|
+
CustomForm = Class.new(Patterns::Form)
|
423
|
+
|
424
|
+
form = CustomForm.new(double)
|
425
|
+
|
426
|
+
expect { form.model_name }.to raise_error(Patterns::Form::NoParamKey)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
context "param_key is defined" do
|
431
|
+
it "returns param_key, route_key and singular_route_key derived from param key" do
|
432
|
+
CustomForm = Class.new(Patterns::Form) do
|
433
|
+
param_key "test_key"
|
434
|
+
end
|
435
|
+
|
436
|
+
form = CustomForm.new(double)
|
437
|
+
result = form.model_name
|
438
|
+
|
439
|
+
expect(result).to have_attributes(
|
440
|
+
param_key: "test_key",
|
441
|
+
route_key: "test_keys",
|
442
|
+
singular_route_key: "test_key"
|
443
|
+
)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
context "resource does not exist" do
|
450
|
+
context "param_key is not defined" do
|
451
|
+
it "raises NoParamKey" do
|
452
|
+
CustomForm = Class.new(Patterns::Form)
|
453
|
+
|
454
|
+
form = CustomForm.new
|
455
|
+
|
456
|
+
expect { form.model_name }.to raise_error(Patterns::Form::NoParamKey)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
context "param_key is defined" do
|
461
|
+
it "returns param_key, route_key and singular_route_key derived from param key" do
|
462
|
+
CustomForm = Class.new(Patterns::Form) do
|
463
|
+
param_key "test_key"
|
464
|
+
end
|
465
|
+
|
466
|
+
form = CustomForm.new
|
467
|
+
result = form.model_name
|
468
|
+
|
469
|
+
expect(result).to have_attributes(
|
470
|
+
param_key: "test_key",
|
471
|
+
route_key: "test_keys",
|
472
|
+
singular_route_key: "test_key"
|
473
|
+
)
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|