eitil 1.3.5 → 1.3.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0a89a4609655c28ab6ee41d45b0c74d34b47d31cef1f494b0d942717cdf5371
4
- data.tar.gz: 905882089b4723ee74710f4877eaecc612ac35c75b9ea954efd9edeb656d8cda
3
+ metadata.gz: 800a7394bf32ae0a35ac26f8af1f854f90161acc373a3cc346422bb71ff58652
4
+ data.tar.gz: '04928eaebb9da031a756d431a2b76893c7d69f9084c48da9066631337014510b'
5
5
  SHA512:
6
- metadata.gz: 8d395e454f20dffb4d7f4a5b9d77944fdbb4603013e5c562ad09d4768642a5df4b98fe8b2e6a10510535b0428aa6f506edab944a787954a8847cac27480df4da
7
- data.tar.gz: c117f0a635d79282a6b7d54dd72a71de77d054c209f25b3c4cd76aae7469320af507c1f35f25b6770041b7b3fbfe3198b9c193c2bec8ed51acf6115a4f75ddcf
6
+ metadata.gz: 07b716769dec7ee55df77d28a4d4fda783868f931f50f8ff44caaa28b28a614c08496ddb1b3c1f6035a4ca6a7ffe98e96547bad2d75872ae5ce3fb20d96b5fa9
7
+ data.tar.gz: 6795a24f73771f86e40a774cb0ab409288eba5b1e82b5b1e97983fd273ee186d6dda22dac75ee99701e3e321c83b855950fc0e156a877f1f1c62aaaa9b664b37
@@ -150,11 +150,20 @@ extended_resources(controller, **kwargs)
150
150
 
151
151
 
152
152
 
153
- ## EitilWrapper::Scopes
153
+ ## EitilWrapper::Records
154
154
 
155
155
  ```ruby
156
156
 
157
- require "eitil_wrapper/scopes"
157
+ # include all below EitilWrapper::Records helpers through:
158
+ require "eitil_wrapper/records"
159
+
160
+ ```
161
+
162
+ ### Scopes
163
+
164
+ ```ruby
165
+
166
+ require "eitil_wrapper/records/scopes"
158
167
 
159
168
  ```
160
169
 
@@ -175,8 +184,6 @@ Scopes are generated through the columns of your model's database table. Which s
175
184
  .{column_name}_before_date(date)
176
185
  .{column_name}_after_date(date)
177
186
  .{column_name}_between_dates(start_date, end_date)
178
- .{column_name}_oldest_first
179
- .{column_name}_newest_first
180
187
 
181
188
  # columns of datatype: date
182
189
  .{column_name}_today
@@ -186,27 +193,96 @@ Scopes are generated through the columns of your model's database table. Which s
186
193
  .{column_name}_before_date(date)
187
194
  .{column_name}_after_date(date)
188
195
  .{column_name}_between_dates(start_date, end_date)
189
- .{column_name}_oldest_first
190
- .{column_name}_newest_first
191
196
 
192
197
  # columns of datatype: integer
193
198
  .{column_name}_equal_to(number)
194
199
  .{column_name}_lower_than(number)
195
200
  .{column_name}_higher_than(number)
196
201
  .{column_name}_between(min, max)
197
- .{column_name}_ascending
198
- .{column_name}_descending
199
202
 
200
203
  # columns of datatype: float
201
204
  .{column_name}_equal_to(number)
202
205
  .{column_name}_lower_than(number)
203
206
  .{column_name}_higher_than(number)
204
207
  .{column_name}_between(min, max)
208
+ ```
209
+
210
+ ### Sorts
211
+
212
+
213
+ ```ruby
214
+
215
+ require "eitil_wrapper/records/sorts"
216
+
217
+ ```
218
+
219
+ Sorts are generated through the columns of your model's database table. Which sorts are generated depends on the datatype of a column. A sort method is defined only if it does not already responds to another method of the same name. The sorts generated are:
220
+
221
+ ```ruby
222
+ # require "eitil_wrapper/scopes/default_scopes"
223
+
224
+ # columns of datatype: datetime
225
+ .{column_name}_oldest_first
226
+ .{column_name}_newest_first
227
+
228
+ # columns of datatype: date
229
+ .{column_name}_oldest_first
230
+ .{column_name}_newest_first
231
+
232
+ # columns of datatype: integer
233
+ .{column_name}_ascending
234
+ .{column_name}_descending
235
+
236
+ # columns of datatype: float
205
237
  .{column_name}_ascending
206
238
  .{column_name}_descending
207
239
  ```
208
240
 
209
241
 
242
+ ### Calculators
243
+
244
+
245
+ ```ruby
246
+
247
+ require "eitil_wrapper/records/calculators"
248
+
249
+ ```
250
+
251
+ Calculators are generated through the columns of your model's database table. Which calculators are generated depends on the datatype of a column. A calculator method is defined only if it does not already responds to another method of the same name. The calculators generated are:
252
+
253
+ ```ruby
254
+ # require "eitil_wrapper/scopes/default_scopes"
255
+
256
+ # columns of datatype: array (serialized)
257
+ .{column_name}_sum # returns all uniq elements in a new, single array
258
+ .{column_name}_sum_i # sum and map to integer
259
+ .{column_name}_sum_f # sum and map to float
260
+ .{column_name}_sum_d # sum and map to decimal
261
+
262
+ # columns of datatype: integer
263
+ .{column_name}_max
264
+ .{column_name}_min
265
+ .{column_name}_sum
266
+ .{column_name}_avg
267
+
268
+ # columns of datatype: float
269
+ .{column_name}_max
270
+ .{column_name}_min
271
+ .{column_name}_sum
272
+ .{column_name}_avg
273
+
274
+ # columns of datatype: decimal
275
+ .{column_name}_max
276
+ .{column_name}_min
277
+ .{column_name}_sum
278
+ .{column_name}_avg
279
+
280
+ # columns of datatype: bigint
281
+ .{column_name}_max
282
+ .{column_name}_min
283
+ .{column_name}_sum
284
+ .{column_name}_avg
285
+ ```
210
286
 
211
287
 
212
288
 
@@ -7,9 +7,16 @@ module EitilWrapper
7
7
 
8
8
  initializer "my_railtie.configure_rails_initialization", options: :after do |app|
9
9
 
10
+ if Object.const_defined?('EitilWrapper::Records::DefaultCalculators')
11
+ ::ApplicationRecord.send(:extend, EitilWrapper::Records::DefaultCalculators)
12
+ end
13
+
14
+ if Object.const_defined?('EitilWrapper::Records::DefaultScopes')
15
+ ::ApplicationRecord.send(:extend, EitilWrapper::Records::DefaultScopes)
16
+ end
10
17
 
11
- if Object.const_defined?('EitilWrapper::Scopes::DefaultScopes')
12
- ::ApplicationRecord.send(:extend, EitilWrapper::Scopes::DefaultScopes)
18
+ if Object.const_defined?('EitilWrapper::Records::DefaultSorts')
19
+ ::ApplicationRecord.send(:extend, EitilWrapper::Records::DefaultSorts)
13
20
  end
14
21
 
15
22
  if Object.const_defined?('EitilWrapper::Callbacks::HelperMethods')
@@ -0,0 +1,104 @@
1
+
2
+ # require "eitil_wrapper/records/default_calculators"
3
+
4
+ # require "eitil_wrapper/railtie" to run the dynamic dispatch as an init hook during boot
5
+ require "eitil_wrapper/railtie"
6
+
7
+ module EitilWrapper
8
+ module Records
9
+ module DefaultCalculators
10
+
11
+ Eitil::ApplicationRecordModules << self
12
+
13
+ SharableNumberCalculators = -> (_class, column) {
14
+ _class.eitil_calculator :"#{column}_max", -> { _class.maximum(column) }
15
+ _class.eitil_calculator :"#{column}_min", -> { _class.minimum(column) }
16
+ _class.eitil_calculator :"#{column}_sum", -> { _class.sum(column) }
17
+ _class.eitil_calculator :"#{column}_avg", -> { _class.average(column) }
18
+ }
19
+
20
+ SharableIterableCalculators = -> (_class, column) {
21
+ _class.eitil_calculator :"#{column}_sum", -> { _class.pluck(column).flatten!.uniq! }
22
+ _class.eitil_calculator :"#{column}_sum_i", -> { _class.pluck(column).flatten!.uniq!.map(&:to_i) }
23
+ _class.eitil_calculator :"#{column}_sum_f", -> { _class.pluck(column).flatten!.uniq!.map(&:to_f) }
24
+ _class.eitil_calculator :"#{column}_sum_d", -> { _class.pluck(column).flatten!.uniq!.map(&:to_d) }
25
+ }
26
+
27
+ def inherited(subclass)
28
+ super
29
+ return if Eitil.skip_default_calculators_for_models.include?(subclass.to_s.to_sym)
30
+
31
+ # Set the proper table_names for namespaced models. Without setting this,
32
+ # Rails run into problems due to the fact that the first call to the model's
33
+ # constant triggers this initializer first, and only thereafter the model file
34
+ # which sets the correct table_name through a macro.
35
+
36
+ namespaced_class = subclass.to_s.include?('::')
37
+ subclass.table_name = subclass.to_s.gsub('::', '_').downcase.pluralize if namespaced_class
38
+
39
+ subclass.use_eitil_calculators
40
+
41
+ rescue => e
42
+ puts "default calculators failed for class '#{subclass}' with expected table '#{subclass.table_name}' because of #{e.class} and '#{e.to_s.split(' ').first}'"
43
+ end
44
+
45
+ def use_eitil_calculators
46
+ return if abstract_class?
47
+
48
+ # text[] is postgresql's datatype for serialized arrays
49
+ # numeric is postgresql's datatype for decimals
50
+ # double precision is postgresql's datatype for floats
51
+
52
+
53
+ %w[integer bigint double\ precision numeric].each do |_type|
54
+ send :"create_eitil_#{_type.gsub(' ','_')}_calculators"
55
+ end
56
+
57
+ create_array_calculators
58
+ end
59
+
60
+ def eitil_calculator(_name, _proc)
61
+ # skip calculator methods for primary and foreign key columns
62
+ return if _name.to_s =~ /^id_[a-z]{1,}$/ || _name.to_s =~ /_id_[a-z]{1,}$/
63
+
64
+ define_singleton_method(_name) { _proc.call } unless respond_to? _name
65
+ end
66
+
67
+ def calculator_columns_of_type(data_type)
68
+ columns_hash.select { |column,v| v.sql_type == data_type }
69
+ end
70
+
71
+ def create_eitil_integer_calculators
72
+ calculator_columns_of_type("integer")&.map do |column, object|
73
+ SharableNumberCalculators.call self, column
74
+ end
75
+ end
76
+
77
+ def create_eitil_bigint_calculators
78
+ calculator_columns_of_type("bigint")&.map do |column, object|
79
+ SharableNumberCalculators.call self, column
80
+ end
81
+ end
82
+
83
+ def create_eitil_double_precision_calculators
84
+ calculator_columns_of_type("double\ precision")&.map do |column, object|
85
+ SharableNumberCalculators.call self, column
86
+ end
87
+ end
88
+
89
+ def create_eitil_numeric_calculators
90
+ calculator_columns_of_type("numeric")&.map do |column, object|
91
+ SharableNumberCalculators.call self, column
92
+ end
93
+ end
94
+
95
+ def create_array_calculators
96
+ columns = columns_hash.select { |column,v| v.sql_type == "text" && v.default == "{}" }
97
+ columns&.map do |column, object|
98
+ SharableIterableCalculators.call self, column
99
+ end
100
+ end
101
+
102
+ end
103
+ end
104
+ end
@@ -1,11 +1,11 @@
1
1
 
2
- # require "eitil_wrapper/scopes/default_scopes"
2
+ # require "eitil_wrapper/records/default_scopes"
3
3
 
4
4
  # require "eitil_wrapper/railtie" to run the dynamic dispatch as an init hook during boot
5
5
  require "eitil_wrapper/railtie"
6
6
 
7
7
  module EitilWrapper
8
- module Scopes
8
+ module Records
9
9
  module DefaultScopes
10
10
 
11
11
  Eitil::ApplicationRecordModules << self
@@ -19,9 +19,6 @@ module EitilWrapper
19
19
  _class.eitil_scope :"#{column}_before_date", -> (date) { where("#{column} = ?", date) }
20
20
  _class.eitil_scope :"#{column}_after_date", -> (date) { where("#{column} = ?", date) }
21
21
  _class.eitil_scope :"#{column}_between_dates", -> (from, till) { where("#{column} >= ? and #{column} <= ?", from, till) }
22
-
23
- _class.eitil_scope :"#{column}_oldest_first", -> { order("#{column} ASC") }
24
- _class.eitil_scope :"#{column}_newest_first", -> { order("#{column} DESC") }
25
22
  }
26
23
 
27
24
  SharableNumScopes = -> (_class, column) {
@@ -29,9 +26,6 @@ module EitilWrapper
29
26
  _class.eitil_scope :"#{column}_lower_than", -> (number) { where("#{column} = <", number) }
30
27
  _class.eitil_scope :"#{column}_higher_than", -> (number) { where("#{column} = >", number) }
31
28
  _class.eitil_scope :"#{column}_between", -> (min, max) { where("#{column} >= ? and #{column} <= ?", min, max) }
32
-
33
- _class.eitil_scope :"#{column}_ascending", -> { order("#{column} ASC") }
34
- _class.eitil_scope :"#{column}_descending", -> { order("#{column} DESC") }
35
29
  }
36
30
 
37
31
  def inherited(subclass)
@@ -42,13 +36,14 @@ module EitilWrapper
42
36
  # Rails run into problems due to the fact that the first call to the model's
43
37
  # constant triggers this initializer first, and only thereafter the model file
44
38
  # which sets the correct table_name through a macro.
39
+
45
40
  namespaced_class = subclass.to_s.include?('::')
46
41
  subclass.table_name = subclass.to_s.gsub('::', '_').downcase.pluralize if namespaced_class
47
42
 
48
43
  subclass.use_eitil_scopes
49
44
 
50
45
  rescue => e
51
- puts "default scopes failed for #{subclass} because of #{e.class} and '#{e.to_s.split(' ').first}'"
46
+ puts "default scopes failed for class '#{subclass}' with expected table '#{subclass.table_name}' because of #{e.class} and '#{e.to_s.split(' ').first}'"
52
47
  end
53
48
 
54
49
  def use_eitil_scopes
@@ -97,4 +92,4 @@ module EitilWrapper
97
92
 
98
93
  end
99
94
  end
100
- end
95
+ end
@@ -0,0 +1,81 @@
1
+
2
+ # require "eitil_wrapper/records/default_sorts"
3
+
4
+ # require "eitil_wrapper/railtie" to run the dynamic dispatch as an init hook during boot
5
+ require "eitil_wrapper/railtie"
6
+
7
+
8
+ module EitilWrapper
9
+ module Records
10
+ module DefaultSorts
11
+
12
+ Eitil::ApplicationRecordModules << self
13
+
14
+ SharableDateSorts = -> (_class, column) {
15
+ _class.eitil_sort :"#{column}_oldest_first", -> { _class.order("#{column} ASC") }
16
+ _class.eitil_sort :"#{column}_newest_first", -> { _class.order("#{column} DESC") }
17
+ }
18
+
19
+ SharableNumSorts = -> (_class, column) {
20
+ _class.eitil_sort :"#{column}_ascending", -> { _class.order("#{column} ASC") }
21
+ _class.eitil_sort :"#{column}_descending", -> { _class.order("#{column} DESC") }
22
+ }
23
+
24
+ def inherited(subclass)
25
+ super
26
+ return if Eitil.skip_default_sorts_for_models.include?(subclass.to_s.to_sym)
27
+
28
+ # Set the proper table_names for namespaced models. Without setting this,
29
+ # Rails run into problems due to the fact that the first call to the model's
30
+ # constant triggers this initializer first, and only thereafter the model file
31
+ # which sets the correct table_name through a macro.
32
+
33
+ namespaced_class = subclass.to_s.include?('::')
34
+ subclass.table_name = subclass.to_s.gsub('::', '_').downcase.pluralize if namespaced_class
35
+
36
+ subclass.use_eitil_sorts
37
+
38
+ rescue => e
39
+ puts "default sorts failed for class '#{subclass}' with expected table '#{subclass.table_name}' because of #{e.class} and '#{e.to_s.split(' ').first}'"
40
+ end
41
+
42
+ def use_eitil_sorts
43
+ return if abstract_class?
44
+ %i[datetime date integer float].each { |_type| send :"create_eitil_#{_type}_sorts" }
45
+ end
46
+
47
+ def eitil_sort(_name, _proc)
48
+ define_singleton_method(_name) { _proc.call } unless respond_to? _name
49
+ end
50
+
51
+ def sort_columns_of_type(data_type)
52
+ columns_hash.select { |column,v| v.sql_type_metadata.type == data_type }
53
+ end
54
+
55
+ def create_eitil_datetime_sorts
56
+ columns_of_type(:datetime)&.map do |column, object|
57
+ SharableDateSorts.call self, column
58
+ end
59
+ end
60
+
61
+ def create_eitil_date_sorts
62
+ columns_of_type(:date)&.map do |column, object|
63
+ SharableDateSorts.call self, column
64
+ end
65
+ end
66
+
67
+ def create_eitil_integer_sorts
68
+ columns_of_type(:integer)&.map do |column, object|
69
+ SharableNumSorts.call self, column
70
+ end
71
+ end
72
+
73
+ def create_eitil_float_sorts
74
+ columns_of_type(:float)&.map do |column, object|
75
+ SharableNumSorts.call self, column
76
+ end
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,4 @@
1
+
2
+ require "eitil_wrapper/records/default_scopes"
3
+ require "eitil_wrapper/records/default_calculators"
4
+ require "eitil_wrapper/records/default_sorts"
@@ -2,7 +2,7 @@
2
2
  require "eitil_wrapper"
3
3
 
4
4
  require "eitil_wrapper/jobs"
5
- require "eitil_wrapper/scopes"
5
+ require "eitil_wrapper/records"
6
6
  require "eitil_wrapper/routes"
7
7
  require "eitil_wrapper/callbacks"
8
8
  require "eitil_wrapper/decorators"
data/lib/eitil/railtie.rb CHANGED
@@ -31,10 +31,14 @@ module Eitil
31
31
 
32
32
  Eitil.mattr_accessor :controller_ivars,
33
33
  :skip_default_scopes_for_models,
34
+ :skip_default_calculators_for_models,
35
+ :skip_default_sorts_for_models,
34
36
  :skip_callback_helper_methods_for_models
35
37
 
36
- Eitil.controller_ivars ||= []
37
- Eitil.skip_default_scopes_for_models ||= []
38
+ Eitil.controller_ivars ||= []
39
+ Eitil.skip_default_scopes_for_models ||= []
40
+ Eitil.skip_default_calculators_for_models ||= []
41
+ Eitil.skip_default_sorts_for_models ||= []
38
42
  Eitil.skip_callback_helper_methods_for_models ||= []
39
43
 
40
44
  def Eitil.set_config(&block)
data/lib/eitil/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Eitil
2
2
 
3
- VERSION = '1.3.5'
3
+ VERSION = '1.3.9'
4
4
 
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eitil
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 1.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jurriaan Schrofer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-20 00:00:00.000000000 Z
11
+ date: 2021-10-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -207,7 +207,6 @@ files:
207
207
  - eitil_core/lib/eitil_core/hash/auto_dig.rb
208
208
  - eitil_core/lib/eitil_core/hash/transform_string_values.rb
209
209
  - eitil_core/lib/eitil_core/kernel.rb
210
- - eitil_core/lib/eitil_core/kernel/always_require_relative.rb
211
210
  - eitil_core/lib/eitil_core/kernel/loadquire.rb
212
211
  - eitil_core/lib/eitil_core/kernel/loadquire_bang.rb
213
212
  - eitil_core/lib/eitil_core/lookups.rb
@@ -284,13 +283,15 @@ files:
284
283
  - eitil_wrapper/lib/eitil_wrapper/jobs/new_job_now.rb
285
284
  - eitil_wrapper/lib/eitil_wrapper/jobs/single_method_job.rb
286
285
  - eitil_wrapper/lib/eitil_wrapper/railtie.rb
286
+ - eitil_wrapper/lib/eitil_wrapper/records.rb
287
+ - eitil_wrapper/lib/eitil_wrapper/records/default_calculators.rb
288
+ - eitil_wrapper/lib/eitil_wrapper/records/default_scopes.rb
289
+ - eitil_wrapper/lib/eitil_wrapper/records/default_sorts.rb
287
290
  - eitil_wrapper/lib/eitil_wrapper/request_logger.rb
288
291
  - eitil_wrapper/lib/eitil_wrapper/request_logger/controller_mixin.rb
289
292
  - eitil_wrapper/lib/eitil_wrapper/request_logger/logger_job.rb
290
293
  - eitil_wrapper/lib/eitil_wrapper/routes.rb
291
294
  - eitil_wrapper/lib/eitil_wrapper/routes/extended_resources.rb
292
- - eitil_wrapper/lib/eitil_wrapper/scopes.rb
293
- - eitil_wrapper/lib/eitil_wrapper/scopes/default_scopes.rb
294
295
  - lib/eitil.rb
295
296
  - lib/eitil/all.rb
296
297
  - lib/eitil/railtie.rb
@@ -470,7 +471,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
470
471
  - !ruby/object:Gem::Version
471
472
  version: '0'
472
473
  requirements: []
473
- rubygems_version: 3.1.2
474
+ rubygems_version: 3.0.9
474
475
  signing_key:
475
476
  specification_version: 4
476
477
  summary: Eitil (eitje utility) never stops increasing your life's efficacy and productivity,
@@ -1,21 +0,0 @@
1
-
2
- # require "eitil_core/kernel/always_require_relative"
3
-
4
- Kernel.module_eval do
5
-
6
- def always_require_relative(current_path, relative_path, extension = '.rb')
7
-
8
- unless Object.const_defined?('Rails')
9
- return require_relative(path)
10
- end
11
-
12
- absolute_path = File.expand_path(relative_path, current_path).concat(extension)
13
-
14
- if Rails.env.development?
15
- load(absolute_path)
16
- else
17
- require(absolute_path)
18
- end
19
- end
20
-
21
- end
@@ -1,2 +0,0 @@
1
-
2
- require "eitil_wrapper/scopes/default_scopes"