eitil 1.3.5 → 1.3.6

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: b0a89a4609655c28ab6ee41d45b0c74d34b47d31cef1f494b0d942717cdf5371
4
- data.tar.gz: 905882089b4723ee74710f4877eaecc612ac35c75b9ea954efd9edeb656d8cda
3
+ metadata.gz: fd9d35211d3f61c2a37a33f09bb080fc91801591270c9fabdb199d1abb6b3f5d
4
+ data.tar.gz: 7e8d7a580c60fe77661a0bfd276c02e55936d870103a66b15f6ebb4090c914e8
5
5
  SHA512:
6
- metadata.gz: 8d395e454f20dffb4d7f4a5b9d77944fdbb4603013e5c562ad09d4768642a5df4b98fe8b2e6a10510535b0428aa6f506edab944a787954a8847cac27480df4da
7
- data.tar.gz: c117f0a635d79282a6b7d54dd72a71de77d054c209f25b3c4cd76aae7469320af507c1f35f25b6770041b7b3fbfe3198b9c193c2bec8ed51acf6115a4f75ddcf
6
+ metadata.gz: c686f8f249fcf7d3418571d9f62adde2403e7a2d4f45a435d9c61455afdaed354332a80f88f4b7e587e9c96e690a27dc10fae81fbb61d2a452c9631525736d18
7
+ data.tar.gz: 5c0c96c615314e07fe44514bd34d5298592f47a3fe4b1fc1f63555fa3acb8d72cb8db04e124259ce44873ae58def846cdd67c48e79504f5cee09251686cf04cf
@@ -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,93 @@ 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
+
259
+ # columns of datatype: integer
260
+ .{column_name}_max
261
+ .{column_name}_min
262
+ .{column_name}_sum
263
+ .{column_name}_avg
264
+
265
+ # columns of datatype: float
266
+ .{column_name}_max
267
+ .{column_name}_min
268
+ .{column_name}_sum
269
+ .{column_name}_avg
270
+
271
+ # columns of datatype: decimal
272
+ .{column_name}_max
273
+ .{column_name}_min
274
+ .{column_name}_sum
275
+ .{column_name}_avg
276
+
277
+ # columns of datatype: bigint
278
+ .{column_name}_max
279
+ .{column_name}_min
280
+ .{column_name}_sum
281
+ .{column_name}_avg
282
+ ```
210
283
 
211
284
 
212
285
 
@@ -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,102 @@
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
+ }
23
+
24
+ def inherited(subclass)
25
+ super
26
+ return if Eitil.skip_default_calculators_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_calculators
37
+
38
+ rescue => e
39
+ puts "default calculators failed for #{subclass} because of #{e.class} and '#{e.to_s.split(' ').first}'"
40
+ end
41
+
42
+ def use_eitil_calculators
43
+ return if abstract_class?
44
+
45
+ # text[] is postgresql's datatype for serialized arrays
46
+ # numeric is postgresql's datatype for decimals
47
+ # double precision is postgresql's datatype for floats
48
+
49
+
50
+ %w[integer bigint double\ precision numeric].each do |_type|
51
+ send :"create_eitil_#{_type.gsub(' ','_')}_calculators"
52
+ end
53
+
54
+ create_array_calculators
55
+ end
56
+
57
+ def eitil_calculator(_name, _proc)
58
+ # skip calculator methods for primary and foreign key columns
59
+ return if _name.to_s =~ /^id_[a-z]{1,}$/ || _name.to_s =~ /_id_[a-z]{1,}$/
60
+
61
+ define_singleton_method(_name) { _proc.call } unless respond_to? _name
62
+ end
63
+
64
+ def calculator_columns_of_type(data_type)
65
+ columns_hash.select { |column,v| v.sql_type == data_type }
66
+ end
67
+
68
+ def create_eitil_integer_calculators
69
+ calculator_columns_of_type("integer")&.map do |column, object|
70
+ SharableNumberCalculators.call self, column
71
+ end
72
+ end
73
+
74
+ def create_eitil_bigint_calculators
75
+ calculator_columns_of_type("bigint")&.map do |column, object|
76
+ SharableNumberCalculators.call self, column
77
+ end
78
+ end
79
+
80
+ def create_eitil_double_precision_calculators
81
+ calculator_columns_of_type("double\ precision")&.map do |column, object|
82
+ SharableNumberCalculators.call self, column
83
+ end
84
+ end
85
+
86
+ def create_eitil_numeric_calculators
87
+ calculator_columns_of_type("numeric")&.map do |column, object|
88
+ SharableNumberCalculators.call self, column
89
+ end
90
+ end
91
+
92
+ def create_array_calculators
93
+ columns = columns_hash.select { |column,v| v.sql_type == "text" && v.default == "{}" }
94
+ columns&.map do |column, object|
95
+ SharableIterableCalculators.call self, column
96
+ end
97
+ end
98
+
99
+ end
100
+ end
101
+ end
102
+
@@ -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,6 +36,7 @@ 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
 
@@ -61,6 +56,7 @@ module EitilWrapper
61
56
  end
62
57
 
63
58
  def columns_of_type(data_type)
59
+ binding.pry if $pry
64
60
  columns_hash.select { |column,v| v.sql_type_metadata.type == data_type }
65
61
  end
66
62
 
@@ -97,4 +93,4 @@ module EitilWrapper
97
93
 
98
94
  end
99
95
  end
100
- end
96
+ end
@@ -0,0 +1,80 @@
1
+ # require "eitil_wrapper/records/default_sorts"
2
+
3
+ # require "eitil_wrapper/railtie" to run the dynamic dispatch as an init hook during boot
4
+ require "eitil_wrapper/railtie"
5
+
6
+
7
+ module EitilWrapper
8
+ module Records
9
+ module DefaultSorts
10
+
11
+ Eitil::ApplicationRecordModules << self
12
+
13
+ SharableDateSorts = -> (_class, column) {
14
+ _class.eitil_sort :"#{column}_oldest_first", -> { _class.order("#{column} ASC") }
15
+ _class.eitil_sort :"#{column}_newest_first", -> { _class.order("#{column} DESC") }
16
+ }
17
+
18
+ SharableNumSorts = -> (_class, column) {
19
+ _class.eitil_sort :"#{column}_ascending", -> { _class.order("#{column} ASC") }
20
+ _class.eitil_sort :"#{column}_descending", -> { _class.order("#{column} DESC") }
21
+ }
22
+
23
+ def inherited(subclass)
24
+ super
25
+ return if Eitil.skip_default_sorts_for_models.include?(subclass.to_s.to_sym)
26
+
27
+ # Set the proper table_names for namespaced models. Without setting this,
28
+ # Rails run into problems due to the fact that the first call to the model's
29
+ # constant triggers this initializer first, and only thereafter the model file
30
+ # which sets the correct table_name through a macro.
31
+
32
+ namespaced_class = subclass.to_s.include?('::')
33
+ subclass.table_name = subclass.to_s.gsub('::', '_').downcase.pluralize if namespaced_class
34
+
35
+ subclass.use_eitil_sorts
36
+
37
+ rescue => e
38
+ puts "default sorts failed for #{subclass} because of #{e.class} and '#{e.to_s.split(' ').first}'"
39
+ end
40
+
41
+ def use_eitil_sorts
42
+ return if abstract_class?
43
+ %i[datetime date integer float].each { |_type| send :"create_eitil_#{_type}_sorts" }
44
+ end
45
+
46
+ def eitil_sort(_name, _proc)
47
+ define_singleton_method(_name) { _proc.call } unless respond_to? _name
48
+ end
49
+
50
+ def sort_columns_of_type(data_type)
51
+ columns_hash.select { |column,v| v.sql_type_metadata.type == data_type }
52
+ end
53
+
54
+ def create_eitil_datetime_sorts
55
+ columns_of_type(:datetime)&.map do |column, object|
56
+ SharableDateSorts.call self, column
57
+ end
58
+ end
59
+
60
+ def create_eitil_date_sorts
61
+ columns_of_type(:date)&.map do |column, object|
62
+ SharableDateSorts.call self, column
63
+ end
64
+ end
65
+
66
+ def create_eitil_integer_sorts
67
+ columns_of_type(:integer)&.map do |column, object|
68
+ SharableNumSorts.call self, column
69
+ end
70
+ end
71
+
72
+ def create_eitil_float_sorts
73
+ columns_of_type(:float)&.map do |column, object|
74
+ SharableNumSorts.call self, column
75
+ end
76
+ end
77
+
78
+ end
79
+ end
80
+ 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.6'
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.6
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-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -284,13 +284,15 @@ files:
284
284
  - eitil_wrapper/lib/eitil_wrapper/jobs/new_job_now.rb
285
285
  - eitil_wrapper/lib/eitil_wrapper/jobs/single_method_job.rb
286
286
  - eitil_wrapper/lib/eitil_wrapper/railtie.rb
287
+ - eitil_wrapper/lib/eitil_wrapper/records.rb
288
+ - eitil_wrapper/lib/eitil_wrapper/records/default_calculators.rb
289
+ - eitil_wrapper/lib/eitil_wrapper/records/default_scopes.rb
290
+ - eitil_wrapper/lib/eitil_wrapper/records/default_sorts.rb
287
291
  - eitil_wrapper/lib/eitil_wrapper/request_logger.rb
288
292
  - eitil_wrapper/lib/eitil_wrapper/request_logger/controller_mixin.rb
289
293
  - eitil_wrapper/lib/eitil_wrapper/request_logger/logger_job.rb
290
294
  - eitil_wrapper/lib/eitil_wrapper/routes.rb
291
295
  - 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
296
  - lib/eitil.rb
295
297
  - lib/eitil/all.rb
296
298
  - lib/eitil/railtie.rb
@@ -470,7 +472,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
470
472
  - !ruby/object:Gem::Version
471
473
  version: '0'
472
474
  requirements: []
473
- rubygems_version: 3.1.2
475
+ rubygems_version: 3.0.9
474
476
  signing_key:
475
477
  specification_version: 4
476
478
  summary: Eitil (eitje utility) never stops increasing your life's efficacy and productivity,
@@ -1,2 +0,0 @@
1
-
2
- require "eitil_wrapper/scopes/default_scopes"