nxt_support 0.1.9 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 49e1e0e7ded712c9afed6b38eb1f8fd55cbedf8d19e7cddb38d5cfca2dbe40ca
4
- data.tar.gz: 2d5ba89926295a604a8d9ec0e4b2acc0fb3871523955d8821b6c2a28befeca08
3
+ metadata.gz: 14151213160e609dc893ae3113a4cfb1eb452ad20f0fe99b7e604e1f20376971
4
+ data.tar.gz: 4fea5f3185b01a3730de9cf418c9c10b14c2bbc742eb5dcb0dbe28ee36ce6fdc
5
5
  SHA512:
6
- metadata.gz: aeedfe831a032f44552ab22b5d8023742c3606b2764bc3532ec91cdbd218fad57830985199c68e6fe90dcccd0bb6ecfa333e5b67925a0d0dbb95f3fd70d93184
7
- data.tar.gz: 268ead8c32f8c8e182ce11ce66d614f25b84d395352cf64a742c6cea587b71dc1af47625ba2b20227872c53c512e3e2617ae4451b982acd0b6c39f70cb51a5f5
6
+ metadata.gz: c96c5be6ec63d22ae72652f8ece297945a32ea0c4c972b03ec9234da864663f629c45ddd8bf76e1b26b2484744c25de91dbb0a1e4c18d44814b5620f9fac254c
7
+ data.tar.gz: 4d7b2944ede23aaf2e568d026bd193019a19b4bcd42ae45612c817c63882bf07d46c81bc6fbb6593833d4236d28a208cea2228e8047a4ae39336943fcf6d0ffe
data/.circleci/config.yml CHANGED
@@ -2,18 +2,31 @@
2
2
  #
3
3
  # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
4
  #
5
- version: 2
5
+ version: 2.1
6
+
7
+ workflows:
8
+ build:
9
+ jobs:
10
+ - build:
11
+ matrix:
12
+ parameters:
13
+ ruby-version: ["2.6.8", "2.7.4", "3.0.2"]
14
+
6
15
  jobs:
7
16
  build:
17
+ parameters:
18
+ ruby-version:
19
+ type: string
20
+
8
21
  docker:
9
22
  # specify the version you desire here
10
- - image: circleci/ruby:2.6.4-node
23
+ - image: circleci/ruby:<< parameters.ruby-version >>-node
11
24
 
12
25
  working_directory: ~/repo
13
26
 
14
27
  steps:
15
28
  - checkout
16
-
29
+
17
30
  - run:
18
31
  name: Install apt dependencies
19
32
  command: |
@@ -26,7 +39,7 @@ jobs:
26
39
  - restore_cache:
27
40
  keys:
28
41
  - v1-dependencies-{{ checksum "Gemfile.lock" }}
29
-
42
+
30
43
  - run: gem install bundler
31
44
 
32
45
  - run:
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+ # v0.1.15 2021-03-26
2
+ - Switched Rails dependency to ActiveRecord and ActiveSupport
3
+
4
+ # v0.1.14 2020-11-25
5
+ - Added `NxtSupport::DurationAttributeAccessor`
6
+
7
+ # v0.1.13 2020-11-13
8
+ - Fixed `Email::REGEXP` to be more generous about hostname
9
+
10
+ # v0.1.12 2020-11-11
11
+ - Added `bin/release` script to publish GitHub tags
12
+
13
+ # v0.1.11 2020-10-29
14
+
15
+ - Introduced `NxtSupport::Services::Base`
16
+
17
+ # v0.1.10 2020-10-10
18
+
19
+ - Introduced `NxtSupport::Enum`
20
+ - Deprecated `NxtSupport::EnumHash`
21
+
22
+
1
23
  # v0.1.9 2020-09-09
2
24
 
3
25
  - Fix `NxtSupport::PreprocessAttributes` to use new `nxt_registry 0.3.0` interface
data/Gemfile.lock CHANGED
@@ -1,162 +1,60 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- nxt_support (0.1.9)
4
+ nxt_support (0.2.1)
5
+ activerecord
6
+ activesupport
5
7
  nxt_init
6
8
  nxt_registry
7
- rails
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
11
12
  specs:
12
- actioncable (6.0.3.3)
13
- actionpack (= 6.0.3.3)
14
- nio4r (~> 2.0)
15
- websocket-driver (>= 0.6.1)
16
- actionmailbox (6.0.3.3)
17
- actionpack (= 6.0.3.3)
18
- activejob (= 6.0.3.3)
19
- activerecord (= 6.0.3.3)
20
- activestorage (= 6.0.3.3)
21
- activesupport (= 6.0.3.3)
22
- mail (>= 2.7.1)
23
- actionmailer (6.0.3.3)
24
- actionpack (= 6.0.3.3)
25
- actionview (= 6.0.3.3)
26
- activejob (= 6.0.3.3)
27
- mail (~> 2.5, >= 2.5.4)
28
- rails-dom-testing (~> 2.0)
29
- actionpack (6.0.3.3)
30
- actionview (= 6.0.3.3)
31
- activesupport (= 6.0.3.3)
32
- rack (~> 2.0, >= 2.0.8)
33
- rack-test (>= 0.6.3)
34
- rails-dom-testing (~> 2.0)
35
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
36
- actiontext (6.0.3.3)
37
- actionpack (= 6.0.3.3)
38
- activerecord (= 6.0.3.3)
39
- activestorage (= 6.0.3.3)
40
- activesupport (= 6.0.3.3)
41
- nokogiri (>= 1.8.5)
42
- actionview (6.0.3.3)
43
- activesupport (= 6.0.3.3)
44
- builder (~> 3.1)
45
- erubi (~> 1.4)
46
- rails-dom-testing (~> 2.0)
47
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
48
- activejob (6.0.3.3)
49
- activesupport (= 6.0.3.3)
50
- globalid (>= 0.3.6)
51
- activemodel (6.0.3.3)
52
- activesupport (= 6.0.3.3)
53
- activerecord (6.0.3.3)
54
- activemodel (= 6.0.3.3)
55
- activesupport (= 6.0.3.3)
56
- activestorage (6.0.3.3)
57
- actionpack (= 6.0.3.3)
58
- activejob (= 6.0.3.3)
59
- activerecord (= 6.0.3.3)
60
- marcel (~> 0.3.1)
61
- activesupport (6.0.3.3)
13
+ activemodel (6.1.4.1)
14
+ activesupport (= 6.1.4.1)
15
+ activerecord (6.1.4.1)
16
+ activemodel (= 6.1.4.1)
17
+ activesupport (= 6.1.4.1)
18
+ activesupport (6.1.4.1)
62
19
  concurrent-ruby (~> 1.0, >= 1.0.2)
63
- i18n (>= 0.7, < 2)
64
- minitest (~> 5.1)
65
- tzinfo (~> 1.1)
66
- zeitwerk (~> 2.2, >= 2.2.2)
67
- builder (3.2.4)
68
- coderay (1.1.2)
69
- concurrent-ruby (1.1.7)
70
- crass (1.0.6)
71
- diff-lcs (1.3)
72
- erubi (1.9.0)
73
- globalid (0.4.2)
74
- activesupport (>= 4.2.0)
75
- i18n (1.8.5)
20
+ i18n (>= 1.6, < 2)
21
+ minitest (>= 5.1)
22
+ tzinfo (~> 2.0)
23
+ zeitwerk (~> 2.3)
24
+ coderay (1.1.3)
25
+ concurrent-ruby (1.1.9)
26
+ diff-lcs (1.4.4)
27
+ i18n (1.8.10)
76
28
  concurrent-ruby (~> 1.0)
77
- loofah (2.7.0)
78
- crass (~> 1.0.2)
79
- nokogiri (>= 1.5.9)
80
- mail (2.7.1)
81
- mini_mime (>= 0.1.1)
82
- marcel (0.3.3)
83
- mimemagic (~> 0.3.2)
84
29
  method_source (1.0.0)
85
- mimemagic (0.3.5)
86
- mini_mime (1.0.2)
87
- mini_portile2 (2.4.0)
88
- minitest (5.14.2)
89
- nio4r (2.5.4)
90
- nokogiri (1.10.10)
91
- mini_portile2 (~> 2.4.0)
30
+ minitest (5.14.4)
92
31
  nxt_init (0.1.5)
93
32
  activesupport
94
- nxt_registry (0.3.0)
33
+ nxt_registry (0.3.10)
95
34
  activesupport
96
- pry (0.13.1)
35
+ pry (0.14.0)
97
36
  coderay (~> 1.1)
98
37
  method_source (~> 1.0)
99
- rack (2.2.3)
100
- rack-test (1.1.0)
101
- rack (>= 1.0, < 3)
102
- rails (6.0.3.3)
103
- actioncable (= 6.0.3.3)
104
- actionmailbox (= 6.0.3.3)
105
- actionmailer (= 6.0.3.3)
106
- actionpack (= 6.0.3.3)
107
- actiontext (= 6.0.3.3)
108
- actionview (= 6.0.3.3)
109
- activejob (= 6.0.3.3)
110
- activemodel (= 6.0.3.3)
111
- activerecord (= 6.0.3.3)
112
- activestorage (= 6.0.3.3)
113
- activesupport (= 6.0.3.3)
114
- bundler (>= 1.3.0)
115
- railties (= 6.0.3.3)
116
- sprockets-rails (>= 2.0.0)
117
- rails-dom-testing (2.0.3)
118
- activesupport (>= 4.2.0)
119
- nokogiri (>= 1.6)
120
- rails-html-sanitizer (1.3.0)
121
- loofah (~> 2.3)
122
- railties (6.0.3.3)
123
- actionpack (= 6.0.3.3)
124
- activesupport (= 6.0.3.3)
125
- method_source
126
- rake (>= 0.8.7)
127
- thor (>= 0.20.3, < 2.0)
128
- rake (13.0.1)
129
- rspec (3.9.0)
130
- rspec-core (~> 3.9.0)
131
- rspec-expectations (~> 3.9.0)
132
- rspec-mocks (~> 3.9.0)
133
- rspec-core (3.9.0)
134
- rspec-support (~> 3.9.0)
135
- rspec-expectations (3.9.0)
38
+ rake (13.0.3)
39
+ rspec (3.10.0)
40
+ rspec-core (~> 3.10.0)
41
+ rspec-expectations (~> 3.10.0)
42
+ rspec-mocks (~> 3.10.0)
43
+ rspec-core (3.10.1)
44
+ rspec-support (~> 3.10.0)
45
+ rspec-expectations (3.10.1)
136
46
  diff-lcs (>= 1.2.0, < 2.0)
137
- rspec-support (~> 3.9.0)
138
- rspec-mocks (3.9.0)
47
+ rspec-support (~> 3.10.0)
48
+ rspec-mocks (3.10.2)
139
49
  diff-lcs (>= 1.2.0, < 2.0)
140
- rspec-support (~> 3.9.0)
141
- rspec-support (3.9.0)
50
+ rspec-support (~> 3.10.0)
51
+ rspec-support (3.10.2)
142
52
  rspec_junit_formatter (0.4.1)
143
53
  rspec-core (>= 2, < 4, != 2.12.0)
144
- sprockets (4.0.2)
145
- concurrent-ruby (~> 1.0)
146
- rack (> 1, < 3)
147
- sprockets-rails (3.2.2)
148
- actionpack (>= 4.0)
149
- activesupport (>= 4.0)
150
- sprockets (>= 3.0.0)
151
54
  sqlite3 (1.4.2)
152
- thor (1.0.1)
153
- thread_safe (0.3.6)
154
- tzinfo (1.2.7)
155
- thread_safe (~> 0.1)
156
- websocket-driver (0.7.3)
157
- websocket-extensions (>= 0.1.0)
158
- websocket-extensions (0.1.5)
159
- zeitwerk (2.4.0)
55
+ tzinfo (2.0.4)
56
+ concurrent-ruby (~> 1.0)
57
+ zeitwerk (2.4.2)
160
58
 
161
59
  PLATFORMS
162
60
  ruby
@@ -171,4 +69,4 @@ DEPENDENCIES
171
69
  sqlite3
172
70
 
173
71
  BUNDLED WITH
174
- 2.1.4
72
+ 2.2.25
data/README.md CHANGED
@@ -52,7 +52,7 @@ The `safely_find_or_create_by` method provided by this concern catches such an e
52
52
 
53
53
  ```ruby
54
54
  class Book < ApplicationRecord
55
- include NxtSupport::SafelyFindOrCreateable
55
+ include NxtSupport::SafelyFindOrCreateable
56
56
  end
57
57
 
58
58
  Book.safely_find_or_create_by!(market: 'de', title: 'Moche!')
@@ -64,7 +64,7 @@ The `NxtSupport::AssignableValues` allows you to restrict the possible values fo
64
64
 
65
65
  ```ruby
66
66
  class Book < ApplicationRecord
67
- include NxtSupport::AssignableValues
67
+ include NxtSupport::AssignableValues
68
68
 
69
69
  # You can use a block
70
70
  assignable_values_for :genre do
@@ -136,6 +136,48 @@ book.save
136
136
  book.views #=> "1001"
137
137
  ```
138
138
 
139
+ #### NxtSupport::DurationAttributeAccessor
140
+
141
+ This mixin provides the accessors for `ActiveSupport::Duration` attributes.
142
+ Imagine you have a database table that needs to store some kind of duration data:
143
+
144
+ ```ruby
145
+ ActiveRecord::Schema.define do
146
+ create_table :courses, force: true do |t|
147
+ t.string :class_duration
148
+ t.string :topic_duration
149
+ t.string :total_duration
150
+ end
151
+ end
152
+ ```
153
+
154
+ And an appropriate model:
155
+
156
+ ```ruby
157
+ class Course < ActiveRecord::Base
158
+ include NxtSupport::DurationAttributeAccessor
159
+
160
+ duration_attribute_accessor :class_duration, :topic_duration, :total_duration
161
+ end
162
+ ```
163
+
164
+ You can then pass the `ActiveSupport::Duration` objects as arguments and get them back:
165
+
166
+ ```ruby
167
+ course = Course.new(
168
+ class_duration: 1.hour,
169
+ topic_duration: 1.month,
170
+ total_duration: 1.year
171
+ )
172
+
173
+ # Fields persist in the database as ISO8601-compliant strings
174
+ course # => #<#<Course:0x00007f8bcf2bcfc0>:0x00007f8bcf2c7920 id: nil, class_duration: "PT1H", topic_duration: "P1M", total_duration: "P1Y">
175
+ course.class_duration # => 1 hour
176
+ course.topic_duration # => 1 month
177
+ course.total_duration # => 1 year
178
+ ```
179
+
180
+
139
181
  ### NxtSupport/Serializers
140
182
 
141
183
  Enjoy mixins for your serializers.
@@ -156,22 +198,26 @@ end
156
198
 
157
199
  Enjoy some useful utilities
158
200
 
159
- #### NxtSupport::EnumHash
201
+ #### NxtSupport::Enum
160
202
 
161
- `NxtSupport::EnumHash` is a simple hash with indifferent access to organize a collection of enums.
162
- Keys will be normalized to be underscore and downcase and access with [] is raising a `KeyError` in case there is
163
- no value for the key.
203
+ `NxtSupport::Enum` provides a simple interface to organize enums.
204
+ Values will be normalized to be underscore and downcase and access with [] is raising a `KeyError` in case there is
205
+ no value for the key. There are also normalized readers for all your values.
164
206
 
165
207
  ```ruby
166
208
  class Book
167
- STATES = NxtSupport::EnumHash['draft', 'revised', 'Published', 'in weird State']
209
+ STATES = NxtSupport::Enum['draft', 'revised', 'Published', 'in weird State']
168
210
  end
169
211
 
170
212
  Book::STATES[:draft] # 'draft'
213
+ Book::STATES.draft # 'draft'
171
214
  Book::STATES['revised'] # 'revised'
215
+ Book::STATES.revised # 'revised'
172
216
  Book::STATES['published'] # 'Published'
217
+ Book::STATES.published # 'Published'
173
218
  Book::STATES['Published'] # KeyError
174
219
  Book::STATES['in_weird_state'] # 'in weird State'
220
+ Book::STATES.in_weird_state # 'in weird State'
175
221
 
176
222
  ```
177
223
 
@@ -249,7 +295,7 @@ TestClass.translate_hash(hash, tuple)
249
295
 
250
296
  #### NxtSupport::Crystalizer
251
297
 
252
- `NxtSupport::Crystalizer` crystallizes a shared value from an array of elements and screams in case the value is not
298
+ `NxtSupport::Crystalizer` crystallizes a shared value from an array of elements and screams in case the value is not
253
299
  the same across the collection. This is useful in a scenario where you want to guarantee that certain objects share the same
254
300
  attribute. Let's say you want to ensure that all users in your collection reference the same department, then the idea
255
301
  is that you can crystallize the department from your collection.
@@ -257,10 +303,20 @@ is that you can crystallize the department from your collection.
257
303
  ```ruby
258
304
  NxtSupport::Crystalizer.new(collection: ['andy', 'andy']).call # => 'andy'
259
305
  NxtSupport::Crystalizer.new(collection: []).call # NxtSupport::Crystalizer::Error
260
- NxtSupport::Crystalizer.new(collection: ['andy', 'scotty']).call # NxtSupport::Crystalizer::Error
261
- NxtSupport::Crystalizer.new(collection: insurances, attribute: :effective_at).call # => shared effective_at or error in case of different effective_ats
306
+ NxtSupport::Crystalizer.new(collection: ['andy', 'scotty']).call # NxtSupport::Crystalizer::Error
307
+ NxtSupport::Crystalizer.new(collection: insurances, attribute: :effective_at).call # => shared effective_at or error in case of different effective_ats
308
+ ```
309
+
310
+ or using the refinement
311
+
312
+ ```ruby
313
+ using NxtSupport::Refinements::Crystalizer
314
+
315
+ ['andy', 'andy'].crystalize # => 'andy'
262
316
  ```
263
317
 
318
+ Note that for Ruby versions < 3.0 it only refines the class `Array` instead of the module `Enumerable`.
319
+
264
320
  #### NxtSupport::BirthDate
265
321
 
266
322
  `NxtSupport::BirthDate` takes a date and provides some convenience methods related to age.
@@ -270,6 +326,62 @@ NxtSupport::BirthDate.new(date: '1990-08-08').to_age # => 30
270
326
  NxtSupport::BirthDate.new(date: '1990-08-08').to_age_in_months # => 361
271
327
  ```
272
328
 
329
+ ### NxtSupport/Services
330
+ Enjoy your service objects.
331
+
332
+ #### NxtSupport::Services::Base
333
+
334
+ `NxtSupport::Services::Base` gives you some convenient sugar for service objects.
335
+ Instead of:
336
+ ```ruby
337
+ WeatherFetcher.new(location: 'Heidelberg').call
338
+ ```
339
+
340
+ You can use:
341
+ ```ruby
342
+ WeatherFetcher.call(location: 'Heidelberg')
343
+ ```
344
+
345
+ ##### Usage
346
+ You have to include `NxtSupport::Services::Base` in your service:
347
+ ```ruby
348
+ class WeatherFetcher
349
+ include NxtSupport::Services::Base
350
+
351
+ def call
352
+ 'Getting the weather..'
353
+ end
354
+ end
355
+ ```
356
+
357
+ Use it:
358
+ ```ruby
359
+ WeatherFetcher.call # => 'Getting the weather..'
360
+ ```
361
+
362
+ ##### With a custom method name
363
+ If you implement a method other than `#call`, you can use `#class_interface :your_method`
364
+ ```ruby
365
+ class HomeBuilder
366
+ include NxtSupport::Services::Base
367
+ include NxtInit
368
+
369
+ attr_init :width, :length, :height, :roof_type
370
+
371
+ class_interface :build
372
+
373
+ def build
374
+ "Building #{width}x#{length}x#{height} house with a #{roof_type} roof"
375
+ end
376
+ end
377
+ ```
378
+
379
+ Use it:
380
+ ```ruby
381
+ HomeBuilder.build(width: 20, length: 40, height: 15, roof_type: :pitched)
382
+ # => Building 20x40x15 house with a pitched roof
383
+ ```
384
+
273
385
  ## Development
274
386
 
275
387
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -280,6 +392,21 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
280
392
 
281
393
  Bug reports and pull requests are welcome on GitHub at https://github.com/nxt_insurance/nxt_support.
282
394
 
395
+ ## Publishing
396
+ ### GitHub Tags and Releases
397
+ Use this command to push the tag to the GitHub Releases page as well as to RubyGems:
398
+ ```sh
399
+ bin/release
400
+ ```
401
+
402
+ ### RubyGems
403
+ For pushing to rubygems:
404
+ 1. Make sure you have ownership rights on RubyGems
405
+ 2. Release the new gem version
406
+ ```sh
407
+ bundle exec rake release
408
+ ```
409
+
283
410
  ## License
284
411
 
285
412
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/release ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env sh
2
+
3
+ GEM_VERSION=$(ruby -e '$LOAD_PATH << File.join(File.dirname(__FILE__), "lib"); require "nxt_support/version"; print NxtSupport::VERSION')
4
+
5
+ git tag -m "Release $GEM_VERSION" -a v$GEM_VERSION HEAD
6
+ git push origin --tags
7
+
8
+ bundle exec rake release
@@ -0,0 +1,62 @@
1
+ module NxtSupport
2
+ module DurationAttributeAccessor
3
+ extend ActiveSupport::Concern
4
+
5
+ class_methods do
6
+ def duration_attribute_accessor(*attrs)
7
+ duration_attribute_reader(*attrs)
8
+ duration_attribute_writer(*attrs)
9
+ end
10
+
11
+ def duration_attribute_reader(*attrs)
12
+ attrs.each do |attr_name|
13
+ define_duration_attribute_reader(attr_name)
14
+ end
15
+ end
16
+
17
+ def duration_attribute_writer(*attrs)
18
+ attrs.each do |attr_name|
19
+ define_duration_attribute_writer(attr_name)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def define_duration_attribute_reader(attr_name)
26
+ define_method(attr_name) do
27
+ duration_string = read_attribute(attr_name)
28
+ return if duration_string.nil?
29
+
30
+ ActiveSupport::Duration.parse(duration_string)
31
+ end
32
+ end
33
+
34
+ def define_duration_attribute_writer(attr_name)
35
+ define_method("#{attr_name}=") do |value|
36
+ case value
37
+ when ActiveSupport::Duration
38
+ write_attribute(attr_name, value.iso8601)
39
+ when String
40
+ if is_valid_iso8601_duration?(value)
41
+ write_attribute(attr_name, value)
42
+ else
43
+ raise ArgumentError, "'#{value}' is not a valid iso8601 string"
44
+ end
45
+ when NilClass
46
+ write_attribute(attr_name, value)
47
+ else
48
+ raise ArgumentError, 'Please provide an ActiveSupport::Duration object or an iso8601 formatted string'
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+
55
+ def is_valid_iso8601_duration?(string)
56
+ ActiveSupport::Duration.parse(string)
57
+ true
58
+ rescue ActiveSupport::Duration::ISO8601Parser::ParsingError
59
+ false
60
+ end
61
+ end
62
+ end
@@ -5,8 +5,8 @@ module NxtSupport
5
5
  # (2) No whitespace characters
6
6
  # (3) At least one non-whitespace character before the '@' character
7
7
  # (4) No dot ('.') character directly after the '@' character
8
- # (5) A hostname after the '@' character of at least two non-whitespace characters length
8
+ # (5) A hostname after the '@' character of at least one non-whitespace characters length
9
9
  # (6) At least one top level domain ending (e.g. '.com') after the hostname, separated from the hostname by a dot ('.')
10
- REGEXP = /\A[^@\s]+@[^\.][^@\s]+\.[^@\s]+\z/.freeze
10
+ REGEXP = /\A[^@\s]+@([^.@\s]+\.)+[^.^@\s]+\z/.freeze
11
11
  end
12
12
  end
@@ -3,3 +3,4 @@ require "nxt_support/models/safely_find_or_createable"
3
3
  require "nxt_support/models/indifferently_accessible_json_attrs"
4
4
  require "nxt_support/models/assignable_values"
5
5
  require "nxt_support/models/preprocess_attributes"
6
+ require "nxt_support/models/duration_attribute_accessor"
@@ -0,0 +1,16 @@
1
+ module NxtSupport
2
+ module Refinements
3
+ module Crystalizer
4
+ #
5
+ # For ruby versions < 3.0, refining a module that is already included isn't possible.
6
+ #
7
+ _refined_module_or_class = Gem::Version.new(RUBY_VERSION) < Gem::Version.new('3.0.0') ? Array : Enumerable
8
+
9
+ refine _refined_module_or_class do
10
+ def crystalize(&block)
11
+ ::NxtSupport::Crystalizer.new(collection: self, on_ambiguity: block).call
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1 @@
1
+ require "nxt_support/refinements/crystalizer"
@@ -0,0 +1,33 @@
1
+ module NxtSupport
2
+ module Services
3
+ module Base
4
+ module ClassMethods
5
+ def class_interface(config = :call)
6
+ if config.is_a?(Symbol)
7
+ define_singleton_method config do |*args, **opts|
8
+ build_instance(*args, **opts).send(config)
9
+ end
10
+ else
11
+ raise ArgumentError, "Wrong configuration. Please use 'class_interface :your_method_name'"
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ # Ruby <2.7-specific check. If the gem is updated to 2.7, `**opts` will work.
18
+ def build_instance(*args, **opts)
19
+ if opts.empty?
20
+ new(*args, **{})
21
+ else
22
+ new(*args, **opts)
23
+ end
24
+ end
25
+ end
26
+
27
+ def self.included(base)
28
+ base.extend(ClassMethods)
29
+ base.class_interface
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1 @@
1
+ require "nxt_support/services/base"
@@ -0,0 +1,7 @@
1
+ module NxtSupport
2
+ class Enum::Value < String
3
+ def initialize(value)
4
+ super(value.to_s).freeze
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,43 @@
1
+ module NxtSupport
2
+ class Enum
3
+ def initialize(*keys)
4
+ @store = ActiveSupport::HashWithIndifferentAccess.new
5
+
6
+ keys.each do |key|
7
+ normalized_key = normalized_key(key)
8
+ store[normalized_key] = NxtSupport::Enum::Value.new(key)
9
+ define_getter(normalized_key)
10
+ end
11
+
12
+ freeze
13
+ end
14
+
15
+ def self.[](*keys)
16
+ new(*keys)
17
+ end
18
+
19
+ def [](key)
20
+ store[key] || (raise KeyError, "No value for key '#{key}' in #{store}")
21
+ end
22
+
23
+ def to_h
24
+ store
25
+ end
26
+
27
+ delegate_missing_to :to_h
28
+
29
+ private
30
+
31
+ attr_reader :store
32
+
33
+ def normalized_key(key)
34
+ key.to_s.downcase.underscore.gsub(/\s+/, '_')
35
+ end
36
+
37
+ def define_getter(normalized_key)
38
+ define_singleton_method normalized_key do
39
+ store[normalized_key]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,27 +1,4 @@
1
1
  module NxtSupport
2
- class EnumHash < ActiveSupport::HashWithIndifferentAccess
3
- def initialize(*keys)
4
- super()
5
-
6
- keys.each do |key|
7
- self[normalized_key(key)] = key.to_s
8
- end
9
-
10
- freeze
11
- end
12
-
13
- def self.[](*keys)
14
- new(*keys)
15
- end
16
-
17
- def [](key)
18
- super(key) || (raise KeyError, "No value for key '#{key}' in #{inspect}")
19
- end
20
-
21
- private
22
-
23
- def normalized_key(key)
24
- key.to_s.downcase.underscore.gsub(/\s+/, '_')
25
- end
26
- end
2
+ # Deprecated
3
+ EnumHash = Class.new(Enum)
27
4
  end
@@ -1,4 +1,6 @@
1
+ require_relative 'util/enum'
1
2
  require_relative 'util/enum_hash'
3
+ require_relative 'util/enum/value'
2
4
  require_relative 'util/hash_translator'
3
5
  require_relative 'util/crystalizer'
4
6
  require_relative 'util/birth_date'
@@ -1,3 +1,3 @@
1
1
  module NxtSupport
2
- VERSION = "0.1.9".freeze
2
+ VERSION = "0.2.1".freeze
3
3
  end
data/lib/nxt_support.rb CHANGED
@@ -6,6 +6,8 @@ require "nxt_support/preprocessor"
6
6
  require "nxt_support/models"
7
7
  require "nxt_support/serializers"
8
8
  require "nxt_support/util"
9
+ require "nxt_support/services"
10
+ require "nxt_support/refinements"
9
11
 
10
12
  module NxtSupport
11
13
  end
data/nxt_support.gemspec CHANGED
@@ -5,8 +5,8 @@ require "nxt_support/version"
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "nxt_support"
7
7
  spec.version = NxtSupport::VERSION
8
- spec.authors = ["Nils Sommer", "Andreas Robecke"]
9
- spec.email = ["mail@nilssommer.de", "a.robecke@getsafe.de"]
8
+ spec.authors = ["Nils Sommer", "Andreas Robecke", "Nicolai Stoianov", "Akihiko Ito"]
9
+ spec.email = ["mail@nilssommer.de", "a.robecke@getsafe.de", "n.stoianov@hellogetsafe.com", "abc@akihiko.eu"]
10
10
 
11
11
  spec.summary = "Support through reusable Mixins and Helpers for Ruby on Rails Applications"
12
12
  spec.homepage = "https://github.com/nxt-insurance/nxt_support"
@@ -27,7 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_dependency "rails"
30
+ spec.add_dependency "activerecord"
31
+ spec.add_dependency "activesupport"
31
32
  spec.add_dependency "nxt_init"
32
33
  spec.add_dependency "nxt_registry"
33
34
  spec.add_development_dependency "bundler"
metadata CHANGED
@@ -1,18 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nxt_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nils Sommer
8
8
  - Andreas Robecke
9
- autorequire:
9
+ - Nicolai Stoianov
10
+ - Akihiko Ito
11
+ autorequire:
10
12
  bindir: exe
11
13
  cert_chain: []
12
- date: 2020-09-24 00:00:00.000000000 Z
14
+ date: 2021-09-13 00:00:00.000000000 Z
13
15
  dependencies:
14
16
  - !ruby/object:Gem::Dependency
15
- name: rails
17
+ name: activerecord
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activesupport
16
32
  requirement: !ruby/object:Gem::Requirement
17
33
  requirements:
18
34
  - - ">="
@@ -123,10 +139,12 @@ dependencies:
123
139
  - - ">="
124
140
  - !ruby/object:Gem::Version
125
141
  version: '0'
126
- description:
142
+ description:
127
143
  email:
128
144
  - mail@nilssommer.de
129
145
  - a.robecke@getsafe.de
146
+ - n.stoianov@hellogetsafe.com
147
+ - abc@akihiko.eu
130
148
  executables: []
131
149
  extensions: []
132
150
  extra_rdoc_files: []
@@ -135,6 +153,7 @@ files:
135
153
  - ".editorconfig"
136
154
  - ".gitignore"
137
155
  - ".rspec"
156
+ - ".ruby-version"
138
157
  - ".ruby_version"
139
158
  - ".travis.yml"
140
159
  - CHANGELOG.md
@@ -144,11 +163,13 @@ files:
144
163
  - README.md
145
164
  - Rakefile
146
165
  - bin/console
166
+ - bin/release
147
167
  - bin/rspec
148
168
  - bin/setup
149
169
  - lib/nxt_support.rb
150
170
  - lib/nxt_support/models.rb
151
171
  - lib/nxt_support/models/assignable_values.rb
172
+ - lib/nxt_support/models/duration_attribute_accessor.rb
152
173
  - lib/nxt_support/models/email.rb
153
174
  - lib/nxt_support/models/indifferently_accessible_json_attrs.rb
154
175
  - lib/nxt_support/models/preprocess_attributes.rb
@@ -156,11 +177,17 @@ files:
156
177
  - lib/nxt_support/preprocessor.rb
157
178
  - lib/nxt_support/preprocessors/downcase_preprocessor.rb
158
179
  - lib/nxt_support/preprocessors/strip_preprocessor.rb
180
+ - lib/nxt_support/refinements.rb
181
+ - lib/nxt_support/refinements/crystalizer.rb
159
182
  - lib/nxt_support/serializers.rb
160
183
  - lib/nxt_support/serializers/has_time_attributes.rb
184
+ - lib/nxt_support/services.rb
185
+ - lib/nxt_support/services/base.rb
161
186
  - lib/nxt_support/util.rb
162
187
  - lib/nxt_support/util/birth_date.rb
163
188
  - lib/nxt_support/util/crystalizer.rb
189
+ - lib/nxt_support/util/enum.rb
190
+ - lib/nxt_support/util/enum/value.rb
164
191
  - lib/nxt_support/util/enum_hash.rb
165
192
  - lib/nxt_support/util/hash_translator.rb
166
193
  - lib/nxt_support/version.rb
@@ -173,7 +200,7 @@ metadata:
173
200
  homepage_uri: https://github.com/nxt-insurance/nxt_support
174
201
  source_code_uri: https://github.com/nxt-insurance/nxt_support
175
202
  changelog_uri: https://github.com/nxt-insurance/nxt_support/CHANGELOG.md
176
- post_install_message:
203
+ post_install_message:
177
204
  rdoc_options: []
178
205
  require_paths:
179
206
  - lib
@@ -188,8 +215,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
215
  - !ruby/object:Gem::Version
189
216
  version: '0'
190
217
  requirements: []
191
- rubygems_version: 3.0.8
192
- signing_key:
218
+ rubygems_version: 3.2.22
219
+ signing_key:
193
220
  specification_version: 4
194
221
  summary: Support through reusable Mixins and Helpers for Ruby on Rails Applications
195
222
  test_files: []