rails-patterns 0.4.1 → 0.5.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +70 -0
- data/VERSION +1 -1
- data/lib/patterns/calculation.rb +45 -0
- data/lib/patterns/form.rb +26 -9
- data/lib/rails-patterns.rb +1 -0
- data/rails-patterns.gemspec +5 -3
- data/spec/patterns/calculation_spec.rb +163 -0
- data/spec/patterns/form_spec.rb +96 -50
- data/spec/spec_helper.rb +5 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a0004234c0698b57bbf9960c6431427a1f548df9
|
4
|
+
data.tar.gz: 9891b7eba903e69d516153c5664b9cf0e04c7f90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8aa0d32fc28cb5924dab59cc9a9d088e940cb7d11e19058f7d7bd5fdc25084554655ee48b9ce1e5938e21b5a70358b78a2d4aa0a98ee455b44d6502e6f2eb615
|
7
|
+
data.tar.gz: 3bcec212d6958aeed3e29ff72ffeca10d0dbe726b1376aa42585f171464f726ac36950db8b49c8a9bfc8eaad98c47458b48a4a01c613905f138759a89c243d61
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,6 +6,7 @@ A collection of lightweight, standardized, rails-oriented patterns.
|
|
6
6
|
- [Service - useful for handling processes involving multiple steps](#service)
|
7
7
|
- [Collection - when in need to add a method that relates to the collection as whole](#collection)
|
8
8
|
- [Form - when you need a place for callbacks, want to replace strong parameters or handle virtual/composite resources](#form)
|
9
|
+
- [Calculation - when you need a place for calculating a simple value (numeric, array, hash) and/or cache it](#calculation)
|
9
10
|
|
10
11
|
## Installation
|
11
12
|
|
@@ -274,6 +275,75 @@ ReportConfigurationForm.new
|
|
274
275
|
ReportConfigurationForm.new({ include_extra_data: true, dump_as_csv: true })
|
275
276
|
```
|
276
277
|
|
278
|
+
## Calculation
|
279
|
+
|
280
|
+
### When to use it
|
281
|
+
|
282
|
+
Calculation objects provide a place to calculate simple values (i.e. numeric, arrays, hashes), especially when calculations require interacting with multiple classes, and thus do not fit into any particular one.
|
283
|
+
Calculation objects also provide simple abstraction for caching their results.
|
284
|
+
|
285
|
+
### Assumptions and rules
|
286
|
+
|
287
|
+
* Calculations have to implement `#result` method that returns any value (result of calculation).
|
288
|
+
* Calculations do provide `.set_cache_expiry_every` method, that allows defining caching period.
|
289
|
+
* When `.set_cache_expiry_every` is not used, result is not being cached.
|
290
|
+
* Calculations return result by calling any of following methods: `.calculate`, `.result_for` or `.result`.
|
291
|
+
* First argument passed to calculation is accessible by `#subject` private method.
|
292
|
+
* Arguments hash passed to calculation is accessible by `#options` private method.
|
293
|
+
* Caching takes into account arguments passed when building cache key.
|
294
|
+
* To build cache key, `#cache_key` of each argument value is used if possible.
|
295
|
+
* By default `Rails.cache` is used as cache store.
|
296
|
+
|
297
|
+
### Examples
|
298
|
+
|
299
|
+
#### Declaration
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
class AverageHotelDailyRevenue < Patterns::Calculation
|
303
|
+
set_cache_expiry_every 1.day
|
304
|
+
|
305
|
+
private
|
306
|
+
|
307
|
+
def result
|
308
|
+
reservations.sum(:price) / days_in_year
|
309
|
+
end
|
310
|
+
|
311
|
+
def reservations
|
312
|
+
Reservation.where(
|
313
|
+
date: (beginning_of_year..end_of_year),
|
314
|
+
hotel_id: subject.id
|
315
|
+
)
|
316
|
+
end
|
317
|
+
|
318
|
+
def days_in_year
|
319
|
+
end_of_year.yday
|
320
|
+
end
|
321
|
+
|
322
|
+
def year
|
323
|
+
options.fetch(:year, Date.current.year)
|
324
|
+
end
|
325
|
+
|
326
|
+
def beginning_of_year
|
327
|
+
Date.new(year).beginning_of_year
|
328
|
+
end
|
329
|
+
|
330
|
+
def end_of_year
|
331
|
+
Date.new(year).end_of_year
|
332
|
+
end
|
333
|
+
end
|
334
|
+
```
|
335
|
+
|
336
|
+
#### Usage
|
337
|
+
|
338
|
+
```ruby
|
339
|
+
hotel = Hotel.find(123)
|
340
|
+
AverageHotelDailyRevenue.result_for(hotel)
|
341
|
+
AverageHotelDailyRevenue.result_for(hotel, year: 2015)
|
342
|
+
|
343
|
+
TotalCurrentRevenue.calculate
|
344
|
+
AverageDailyRevenue.result
|
345
|
+
```
|
346
|
+
|
277
347
|
## Further reading
|
278
348
|
|
279
349
|
* [7 ways to decompose fat active record models](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Patterns
|
2
|
+
class Calculation
|
3
|
+
class_attribute :cache_expiry_every
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
@options = args.extract_options!
|
7
|
+
@subject = args.first
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.result(*args)
|
11
|
+
new(*args).cached_result
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
alias_method :result_for, :result
|
16
|
+
alias_method :calculate, :result
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.set_cache_expiry_every(period)
|
20
|
+
self.cache_expiry_every = period
|
21
|
+
end
|
22
|
+
|
23
|
+
def cached_result
|
24
|
+
Rails.cache.fetch(cache_key, expires_in: cache_expiry_period, force: cache_expiry_period.blank?) do
|
25
|
+
result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :subject, :options
|
32
|
+
|
33
|
+
def result
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
def cache_key
|
38
|
+
"#{self.class.name}_#{[subject, options].hash}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def cache_expiry_period
|
42
|
+
self.class.cache_expiry_every
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/patterns/form.rb
CHANGED
@@ -49,6 +49,14 @@ module Patterns
|
|
49
49
|
self
|
50
50
|
end
|
51
51
|
|
52
|
+
def to_param
|
53
|
+
if resource.present? && resource.respond_to?(:to_param)
|
54
|
+
resource.to_param
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
52
60
|
def persisted?
|
53
61
|
if resource.present? && resource.respond_to?(:persisted?)
|
54
62
|
resource.persisted?
|
@@ -58,9 +66,7 @@ module Patterns
|
|
58
66
|
end
|
59
67
|
|
60
68
|
def model_name
|
61
|
-
@model_name ||=
|
62
|
-
new(:param_key).
|
63
|
-
new(param_key)
|
69
|
+
@model_name ||= OpenStruct.new(model_name_attributes)
|
64
70
|
end
|
65
71
|
|
66
72
|
def self.param_key(key = nil)
|
@@ -75,13 +81,24 @@ module Patterns
|
|
75
81
|
|
76
82
|
attr_reader :resource, :form_owner
|
77
83
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
84
|
+
def model_name_attributes
|
85
|
+
if self.class.param_key.present?
|
86
|
+
{
|
87
|
+
param_key: self.class.param_key,
|
88
|
+
route_key: self.class.param_key.pluralize,
|
89
|
+
singular_route_key: self.class.param_key
|
90
|
+
}
|
91
|
+
elsif resource.present? && resource.respond_to?(:model_name)
|
92
|
+
{
|
93
|
+
param_key: resource.model_name.param_key,
|
94
|
+
route_key: resource.model_name.route_key,
|
95
|
+
singular_route_key: resource.model_name.singular_route_key
|
96
|
+
}
|
97
|
+
else
|
98
|
+
raise NoParamKey
|
99
|
+
end
|
83
100
|
end
|
84
|
-
|
101
|
+
|
85
102
|
def build_original_attributes
|
86
103
|
return {} if resource.nil?
|
87
104
|
base_attributes = resource.respond_to?(:attributes) && resource.attributes.symbolize_keys
|
data/lib/rails-patterns.rb
CHANGED
data/rails-patterns.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: rails-patterns 0.
|
5
|
+
# stub: rails-patterns 0.5.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "rails-patterns".freeze
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.5.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["Stevo".freeze]
|
14
|
-
s.date = "2017-
|
14
|
+
s.date = "2017-06-22"
|
15
15
|
s.description = "A collection of lightweight, standardized, rails-oriented patterns.".freeze
|
16
16
|
s.email = "b.kosmowski@selleo.com".freeze
|
17
17
|
s.extra_rdoc_files = [
|
@@ -28,12 +28,14 @@ Gem::Specification.new do |s|
|
|
28
28
|
"Rakefile",
|
29
29
|
"VERSION",
|
30
30
|
"lib/patterns.rb",
|
31
|
+
"lib/patterns/calculation.rb",
|
31
32
|
"lib/patterns/collection.rb",
|
32
33
|
"lib/patterns/form.rb",
|
33
34
|
"lib/patterns/query.rb",
|
34
35
|
"lib/patterns/service.rb",
|
35
36
|
"lib/rails-patterns.rb",
|
36
37
|
"rails-patterns.gemspec",
|
38
|
+
"spec/patterns/calculation_spec.rb",
|
37
39
|
"spec/patterns/collection_spec.rb",
|
38
40
|
"spec/patterns/form_spec.rb",
|
39
41
|
"spec/patterns/query_spec.rb",
|
@@ -0,0 +1,163 @@
|
|
1
|
+
RSpec.describe Patterns::Calculation do
|
2
|
+
before(:all) do
|
3
|
+
class Rails
|
4
|
+
def self.cache
|
5
|
+
@cache ||= ActiveSupport::Cache::MemoryStore.new
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
Object.send(:remove_const, :Rails)
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
Object.send(:remove_const, :CustomCalculation) if defined?(CustomCalculation)
|
16
|
+
Rails.cache.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".result" do
|
20
|
+
it "returns a result of the calculation within a #result method" do
|
21
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
22
|
+
private
|
23
|
+
|
24
|
+
def result
|
25
|
+
50
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
expect(CustomCalculation.result).to eq 50
|
30
|
+
end
|
31
|
+
|
32
|
+
it "#result, #result_for and #calculate are aliases" do
|
33
|
+
CustomCalculation = Class.new(Patterns::Calculation)
|
34
|
+
|
35
|
+
expect(CustomCalculation.method(:result)).to eq CustomCalculation.method(:result_for)
|
36
|
+
expect(CustomCalculation.method(:result)).to eq CustomCalculation.method(:calculate)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "exposes the first argument as a subject" do
|
40
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
41
|
+
private
|
42
|
+
|
43
|
+
def result
|
44
|
+
subject
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
expect(CustomCalculation.result('test')).to eq 'test'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "exposes all keyword arguments using #options" do
|
52
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
53
|
+
private
|
54
|
+
|
55
|
+
def result
|
56
|
+
[options[:arg_1], options[:arg_2]]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
expect(CustomCalculation.result(nil, arg_1: 20, arg_2: 30)).to eq([20, 30])
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "caching" do
|
65
|
+
it "caches result for 'set_cache_expiry_every' period" do
|
66
|
+
travel_to DateTime.new(2017, 1, 1, 12, 0) do
|
67
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
68
|
+
set_cache_expiry_every 1.hour
|
69
|
+
|
70
|
+
class_attribute :counter
|
71
|
+
self.counter = 0
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def result
|
76
|
+
self.class.counter += 1
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
expect(CustomCalculation.result).to eq 1
|
81
|
+
expect(CustomCalculation.result).to eq 1
|
82
|
+
end
|
83
|
+
|
84
|
+
travel_to DateTime.new(2017, 1, 1, 13, 1) do
|
85
|
+
expect(CustomCalculation.result).to eq 2
|
86
|
+
expect(CustomCalculation.result).to eq 2
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "caches result for every option passed" do
|
91
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
92
|
+
set_cache_expiry_every 1.hour
|
93
|
+
|
94
|
+
class_attribute :counter
|
95
|
+
self.counter = 0
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def result
|
100
|
+
self.class.counter += 1
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
expect(CustomCalculation.result(123)).to eq 1
|
105
|
+
expect(CustomCalculation.result(123)).to eq 1
|
106
|
+
expect(CustomCalculation.result(1024)).to eq 2
|
107
|
+
expect(CustomCalculation.result(1024)).to eq 2
|
108
|
+
expect(CustomCalculation.result(1024, arg: 1)).to eq 3
|
109
|
+
expect(CustomCalculation.result(1024, arg: 1)).to eq 3
|
110
|
+
end
|
111
|
+
|
112
|
+
it "caches result for every option passed dependant on the class" do
|
113
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
114
|
+
set_cache_expiry_every 1.hour
|
115
|
+
|
116
|
+
class_attribute :counter
|
117
|
+
self.counter = 0
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
def result
|
122
|
+
self.class.counter += 1
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
DifferentCalculation = Class.new(Patterns::Calculation) do
|
127
|
+
set_cache_expiry_every 1.hour
|
128
|
+
|
129
|
+
class_attribute :counter
|
130
|
+
self.counter = 100
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def result
|
135
|
+
self.class.counter += 1
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
expect(CustomCalculation.result(123)).to eq 1
|
140
|
+
expect(CustomCalculation.result(123)).to eq 1
|
141
|
+
expect(DifferentCalculation.result(123)).to eq 101
|
142
|
+
expect(DifferentCalculation.result(123)).to eq 101
|
143
|
+
|
144
|
+
Object.send(:remove_const, :DifferentCalculation)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "does not cache result if 'set_cache_expiry_every' is not set" do
|
148
|
+
CustomCalculation = Class.new(Patterns::Calculation) do
|
149
|
+
class_attribute :counter
|
150
|
+
self.counter = 0
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def result
|
155
|
+
self.class.counter += 1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
expect(CustomCalculation.result).to eq 1
|
160
|
+
expect(CustomCalculation.result).to eq 2
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/spec/patterns/form_spec.rb
CHANGED
@@ -316,7 +316,7 @@ RSpec.describe Patterns::Form do
|
|
316
316
|
end
|
317
317
|
|
318
318
|
describe "#to_model" do
|
319
|
-
it "
|
319
|
+
it "returns itself" do
|
320
320
|
CustomForm = Class.new(Patterns::Form)
|
321
321
|
|
322
322
|
form = CustomForm.new(double)
|
@@ -345,86 +345,132 @@ RSpec.describe Patterns::Form do
|
|
345
345
|
end
|
346
346
|
end
|
347
347
|
|
348
|
-
describe "#
|
349
|
-
|
350
|
-
context "resource
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
CustomForm = Class.new(Patterns::Form)
|
355
|
-
resource = double(model_name: double(param_key: "resource_key"))
|
356
|
-
|
357
|
-
form = CustomForm.new(resource)
|
358
|
-
result = form.model_name
|
359
|
-
|
360
|
-
expect(result).to respond_to(:param_key)
|
361
|
-
expect(result.param_key).to eq "resource_key"
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
context "param_key is defined" do
|
366
|
-
it "returns param_key" do
|
367
|
-
CustomForm = Class.new(Patterns::Form) do
|
368
|
-
param_key "test_key"
|
369
|
-
end
|
370
|
-
resource = double(model_name: double(param_key: "resource_key"))
|
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)
|
371
354
|
|
372
|
-
|
373
|
-
result = form.model_name
|
355
|
+
form = CustomForm.new(resource)
|
374
356
|
|
375
|
-
|
376
|
-
end
|
377
|
-
end
|
357
|
+
expect(form.to_param).to eq 100
|
378
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)
|
379
365
|
|
380
|
-
|
381
|
-
context "param_key is not defined" do
|
382
|
-
it "raises NoParamKey" do
|
383
|
-
CustomForm = Class.new(Patterns::Form)
|
366
|
+
form = CustomForm.new
|
384
367
|
|
385
|
-
|
368
|
+
expect(form.to_param).to eq nil
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
386
372
|
|
387
|
-
|
388
|
-
|
389
|
-
|
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
|
+
))
|
390
384
|
|
391
|
-
|
392
|
-
|
393
|
-
CustomForm = Class.new(Patterns::Form) do
|
394
|
-
param_key "test_key"
|
395
|
-
end
|
385
|
+
form = CustomForm.new(resource)
|
386
|
+
result = form.model_name
|
396
387
|
|
397
|
-
|
398
|
-
|
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
|
399
395
|
|
400
|
-
|
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"
|
401
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
|
+
)
|
402
415
|
end
|
403
416
|
end
|
404
417
|
end
|
405
418
|
|
406
|
-
context "resource does not
|
419
|
+
context "resource does not respond to #model_name" do
|
407
420
|
context "param_key is not defined" do
|
408
421
|
it "raises NoParamKey" do
|
409
422
|
CustomForm = Class.new(Patterns::Form)
|
410
423
|
|
411
|
-
form = CustomForm.new
|
424
|
+
form = CustomForm.new(double)
|
412
425
|
|
413
426
|
expect { form.model_name }.to raise_error(Patterns::Form::NoParamKey)
|
414
427
|
end
|
415
428
|
end
|
416
429
|
|
417
430
|
context "param_key is defined" do
|
418
|
-
it "returns param_key" do
|
431
|
+
it "returns param_key, route_key and singular_route_key derived from param key" do
|
419
432
|
CustomForm = Class.new(Patterns::Form) do
|
420
433
|
param_key "test_key"
|
421
434
|
end
|
422
435
|
|
423
|
-
form = CustomForm.new
|
436
|
+
form = CustomForm.new(double)
|
424
437
|
result = form.model_name
|
425
438
|
|
426
|
-
expect(result
|
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"
|
427
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
|
+
)
|
428
474
|
end
|
429
475
|
end
|
430
476
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -17,10 +17,14 @@
|
|
17
17
|
#
|
18
18
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
19
19
|
|
20
|
-
require "
|
20
|
+
require "active_support/all"
|
21
|
+
require "active_support/testing/time_helpers"
|
21
22
|
require "pry"
|
23
|
+
require "rails-patterns"
|
22
24
|
|
23
25
|
RSpec.configure do |config|
|
26
|
+
config.include ActiveSupport::Testing::TimeHelpers
|
27
|
+
|
24
28
|
# rspec-expectations config goes here. You can use an alternate
|
25
29
|
# assertion/expectation library such as wrong or the stdlib/minitest
|
26
30
|
# assertions if you prefer.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-patterns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stevo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -111,12 +111,14 @@ files:
|
|
111
111
|
- Rakefile
|
112
112
|
- VERSION
|
113
113
|
- lib/patterns.rb
|
114
|
+
- lib/patterns/calculation.rb
|
114
115
|
- lib/patterns/collection.rb
|
115
116
|
- lib/patterns/form.rb
|
116
117
|
- lib/patterns/query.rb
|
117
118
|
- lib/patterns/service.rb
|
118
119
|
- lib/rails-patterns.rb
|
119
120
|
- rails-patterns.gemspec
|
121
|
+
- spec/patterns/calculation_spec.rb
|
120
122
|
- spec/patterns/collection_spec.rb
|
121
123
|
- spec/patterns/form_spec.rb
|
122
124
|
- spec/patterns/query_spec.rb
|