eitil 0.3.1 → 0.3.6

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: f822863c972553dc89dca4e80fce4b197c89c27f78456342195f46b920fa07f5
4
- data.tar.gz: 0e852adfd5a9127d3d67f349102bb6000121b730a5a42d0628b09beab45723fe
3
+ metadata.gz: 92cb9e9c82e5a3bfac7cbc0b5f662428bac557a2c3abbca8e30c86d60174363a
4
+ data.tar.gz: 20c072c5d8b8ce2e055ff0635472a66fdb11ba4155d770ac3cd600be0c0892da
5
5
  SHA512:
6
- metadata.gz: cc64496f6e70c4d737ddf6bf091988ab01425802852034dd1d0c083bee1cda38ee25381927b498fc74c0094f27c071b71e10b360fc00ac477e81635b509d1915
7
- data.tar.gz: ac2c18d0bd040e892caf008de55550cd09322fb69b09d15efd6adf6d147ce399b8e5aff547603af1311c7ebb86f0a8051da40211791d70042ee4e87a57ef23b3
6
+ metadata.gz: 945e8da34ffe7c89a24c11d2c4f75f2861ed9355ed0ed0c6759cc57d63485d7bb37006be1c4cb4f1fa8c93d13a672b238f4c99ec3110001db917cdc4cc2e02e0
7
+ data.tar.gz: d0a0641152e75e6f100eda08f83a3b253d8d80dd570fb26d76a2649822180e0f3c834da64012bb5d0e61709163fc81dbc7986ec5fa04d8d74faa8fd6a7f290a9
data/README.md CHANGED
@@ -13,11 +13,19 @@ Add this line to your application's Gemfile:
13
13
 
14
14
  ```ruby
15
15
 
16
+ gem 'eitil' # check the latest version on https://rubygems.org/gems/eitil
17
+
18
+ ```
19
+
20
+ Or, if you want a specific branch (requires auth for private branch):
21
+
22
+ ```ruby
23
+
16
24
  gem 'eitil', git: 'https://github.com/eitje-app/eitil_engine', branch: 'production'
17
25
 
18
26
  ```
19
27
 
20
- Or this line, with your own path correctly set, for development purposes:
28
+ Or, for development purposes:
21
29
 
22
30
  ```ruby
23
31
 
@@ -42,15 +50,21 @@ args_to_ivars(binding, *local_vars)
42
50
  # sets specified keywords arguments of the method's local binding to instance variables
43
51
  # call as: all_args_to_ivars binding :user_id, :user_name
44
52
 
45
- all_kwargs_to_ivars(binding)
53
+ all_kwargs_to_ivars(local_binding, namespace=:kwargs)
46
54
  # sets the method's **kwargs argument to instance variables, with each key as the ivar's "@#{name}" and the value as its value
47
55
  # call as: kwargs_to_ivars binding
56
+ # the keywords container name can be overwritten, e.g. the common :attributes
48
57
 
49
58
  set_ivars(*ivars)
50
59
  # sets instance variables named @"#{ivar}" for each symbol passed, by invoking send("set_#{ivar}")
51
60
  # e.g. set_ivars(:user) sets @user with the value returned by your local method .set_user
52
61
  # call as: set_ivars :user, :authentication, :connection
53
62
 
63
+ run_validations(*validations)
64
+ # calls a method for each argument, namespaced as "validate_#{argument}"
65
+ # call as: run_validations(:single_receipt, :single_order)
66
+ # => calls #validate_single_receipt and #validate_single_order
67
+
54
68
  safe_send(method, *args, return_value: nil)
55
69
  # a safe version of .send, which in case of an error rescues and returns return_value (default: nil) instead
56
70
 
@@ -79,10 +93,12 @@ all_methods(include_ancestors = true, grep: nil)
79
93
  ## Module
80
94
 
81
95
  ```ruby
82
- include_concerns_of(*directories)
83
- # includes all models/concerns/{sub_directory}/* within a module or class
96
+ include_concerns_of(*directories, namespace: nil)
97
+ # includes models/concerns/{directories}/* if no namespace if given, or all concerns within the given namespace
84
98
  # call as: include_concerns_of :user, :mail
85
99
  # => includes all modules of models/concerns/user/* and models/oncerns/mail/*
100
+ # or call as: include_concerns_of :request_service, namespace: Eivid::Concerns
101
+ # tip: call Class.included_modules to view all included modules
86
102
  ```
87
103
 
88
104
 
@@ -109,6 +125,16 @@ slice_params(*args)
109
125
 
110
126
 
111
127
 
128
+ ## ApplicationRecord
129
+
130
+ ```ruby
131
+ self.all_associations
132
+ # returns all associations for a given model
133
+ # call as: Environment.all_associations
134
+ ```
135
+
136
+
137
+
112
138
  ## DateTime
113
139
 
114
140
  ```ruby
@@ -151,7 +177,7 @@ decorate(dec_item, dec_method: nil, dec_class: nil, **dec_kwargs)
151
177
  # initializers/eitil.rb
152
178
 
153
179
  Eitil.set_config do |config|
154
- config.get_controller_ivars_method = 'API::VerlofVerzoekenController.controller_ivars' # => [:user, :env]
180
+ config.get_controller_ivars_method = 'API::BaseController.controller_ivars' # => [:user, :env]
155
181
  end
156
182
  ```
157
183
 
@@ -201,14 +227,18 @@ The router wrapper is a single module which is automatically included into your
201
227
 
202
228
  ### Info
203
229
 
204
- The Eitil jobs wrapper enables you to create perform_later jobs on the fly, without the need to create a new class and file. The macro new_job accepts a :method as argument and defines a new method :method_job. The newly defined :method_job, when called, performs the orginal :method in the background. The new_job macro accepts both instance methods and singleton methods, which are defined within there own method scope.
230
+ The Eitil jobs wrapper enables you to create perform_now and perform_later jobs on the fly, without the need to create a new class and file. The macro new_job accepts a :method as argument and defines a new method :method_job. The newly defined :method_job, when called, performs the orginal :method in the background. The new_job macro accepts both instance methods and singleton methods, which are defined within there own method scope. In contrast, the new_job_debugger macro defines a new :method_job_debugger method, which performs in the foreground.
205
231
 
206
232
  ### Job Macro
207
233
 
208
234
  ```ruby
209
- new_job(_method)
210
- # assuming a method :print_hello_world, call as: new_job :hello_world
211
- # => method :hello_world_job
235
+ new_job(_method, *args, **kwargs)
236
+ # assuming a method :hello_world, call as: new_job :hello_world
237
+ # => defines :hello_world_job
238
+
239
+ new_job_debugger(_method, *args, **kwargs)
240
+ # assuming a method :hello_world, call as: new_job_debugger :hello_world
241
+ # => defines :hello_world_job_debugger
212
242
  ```
213
243
 
214
244
  - method is
@@ -223,15 +253,7 @@ The new_job macro is monkey patched into Kernel, therefore no configuration is r
223
253
 
224
254
  ### Info
225
255
 
226
- The Eitil scopes wrapper creates various default scopes for a model, simply through including 'use_eitil_scopes' in the top of your model file, for example:
227
-
228
- ```ruby
229
- # models/user.rb
230
-
231
- class User < ApplicationRecord
232
- use_eitil_scopes
233
- end
234
- ```
256
+ The Eitil scopes wrapper creates various default scopes for a model.
235
257
 
236
258
  ### The Scopes
237
259
 
@@ -263,6 +285,22 @@ Scopes are generated through the columns of your model's database table. Which s
263
285
  .{column_name}_between_dates(start_date, end_date)
264
286
  .{column_name}_oldest_first
265
287
  .{column_name}_newest_first
288
+
289
+ # columns of datatype: integer
290
+ .{column_name}_equal_to(number)
291
+ .{column_name}_lower_than(number)
292
+ .{column_name}_higher_than(number)
293
+ .{column_name}_between(min, max)
294
+ .{column_name}_ascending
295
+ .{column_name}_descending
296
+
297
+ # columns of datatype: float
298
+ .{column_name}_equal_to(number)
299
+ .{column_name}_lower_than(number)
300
+ .{column_name}_higher_than(number)
301
+ .{column_name}_between(min, max)
302
+ .{column_name}_ascending
303
+ .{column_name}_descending
266
304
  ```
267
305
 
268
306
  ### Configuration
@@ -270,3 +308,31 @@ Scopes are generated through the columns of your model's database table. Which s
270
308
  Your models should inherit the module Eitil::DefaultScopes through inclusion in a superclass, such as ApplicationRecord.
271
309
 
272
310
 
311
+
312
+ # Modules
313
+
314
+
315
+
316
+ ## Eitil::Dir
317
+
318
+ ### Info
319
+
320
+ The Eitil::Dir module provides methods which help you introspect your Rails project.
321
+
322
+ ### Methods
323
+
324
+ ```ruby
325
+ Eitil::Dir.contents(directory='app')
326
+ # returns all files and subdirectories of a given directory
327
+
328
+ Eitil::Dir.files(directory='app')
329
+ # returns all files of a given directory
330
+
331
+ Eitil::Dir.subdirs(directory='app')
332
+ # returns all subdirectories of a given directory
333
+
334
+ Eitil::Dir.lines(directory='app')
335
+ # returns the total amount of lines of all files of a given directory
336
+ ```
337
+
338
+
@@ -0,0 +1,21 @@
1
+ module Eitil::Dir
2
+ class << self
3
+
4
+ def contents(directory='app')
5
+ Dir[File.join(directory, '**', '*')]
6
+ end
7
+
8
+ def files(directory='app')
9
+ contents(directory).select { |file| File.file?(file) }
10
+ end
11
+
12
+ def subdirs(directory='app')
13
+ contents(directory).select { |file| File.directory?(file) }
14
+ end
15
+
16
+ def lines(directory='app')
17
+ files(directory).map { |file| File.open(file).count }.sum
18
+ end
19
+
20
+ end
21
+ end
@@ -1,4 +1,4 @@
1
- module ApplicationMonkey
1
+ module ApplicationControllerMonkey
2
2
  extend ActiveSupport::Concern
3
3
  included do
4
4
 
@@ -11,4 +11,4 @@ module ApplicationMonkey
11
11
  end
12
12
  end
13
13
 
14
- ApplicationController.send :include, ApplicationMonkey
14
+ ApplicationController.send :include, ApplicationControllerMonkey
@@ -0,0 +1,16 @@
1
+ require "#{Eitil::Engine.root.to_s}/config/initializers/wrappers/scopes/default_scopes.rb"
2
+
3
+ module ApplicationRecordMonkey
4
+ extend ActiveSupport::Concern
5
+ included do
6
+
7
+ def self.all_associations
8
+ reflect_on_all_associations.map do |assoc|
9
+ { assoc.name => assoc.association_class.to_s.demodulize }
10
+ end.inject &:merge
11
+ end
12
+
13
+ end
14
+ end
15
+
16
+ ApplicationRecord.send :include, ApplicationRecordMonkey
@@ -8,7 +8,7 @@ class Hash
8
8
  return answer if answer
9
9
  end
10
10
 
11
- false
11
+ nil
12
12
  end
13
13
 
14
14
  end
@@ -12,8 +12,8 @@ Kernel.module_eval do
12
12
  end
13
13
  end
14
14
 
15
- def all_kwargs_to_ivars(local_binding)
16
- local_binding.local_variable_get(:kwargs).each do |name, value|
15
+ def all_kwargs_to_ivars(local_binding, namespace=:kwargs)
16
+ local_binding.local_variable_get(namespace).each do |name, value|
17
17
  instance_variable_set "@#{name}", value
18
18
  end
19
19
  end
@@ -24,6 +24,10 @@ Kernel.module_eval do
24
24
  end
25
25
  end
26
26
 
27
+ def run_validations(*validations)
28
+ validations.each { |v| eval "validate_#{v}" }
29
+ end
30
+
27
31
  def safe_call(*args, return_value: nil, &block)
28
32
  block.call self, *args
29
33
  rescue
@@ -1,7 +1,7 @@
1
1
  class Module
2
2
 
3
- def include_concerns_of(*directories)
4
- directories.map! { |dir| dir.to_s.camelcase }
3
+ def include_concerns_of(*directories, namespace: nil)
4
+ directories.map! { |dir| "#{namespace}::#{dir.to_s.camelcase}" }
5
5
 
6
6
  directories.each do |dir|
7
7
  konstants = dir.constantize.constants(false)
@@ -1,18 +1,52 @@
1
1
  Kernel.module_eval do
2
2
 
3
- def new_job(_method)
3
+ # BEWARE: _self is currently not accepted in perform_later jobs due to serialization errors
4
+
5
+ # The cases of 'id' and '_self' both handle instances, with the difference
6
+ # being that 'id' works for objects that have a database record, while '_self'
7
+ # works for non database supported instanes, such as an Exporter instance.
8
+
9
+ def new_job(_method, *args, **kwargs)
4
10
 
5
11
  if instance_methods(false).include? _method
6
- define_method "#{_method}_job" do
7
- Eitil::SingleMethodJob.perform_later(_class: self.class.to_s, _method: _method.to_s, id: id)
12
+ define_method "#{_method}_job" do |_self = nil, *args, **kwargs|
13
+
14
+ Eitil::SingleMethodJob.perform_later(
15
+ *args, _class: self.class.to_s, _method: _method.to_s, id: safe_send(:id), _self: self.to_json, **kwargs
16
+ )
8
17
  end
9
18
 
10
- elsif singleton_methods(false).include? _method
11
- define_singleton_method "#{_method}_job" do
12
- Eitil::SingleMethodJob.perform_later(_class: to_s, _method: _method.to_s)
19
+ elsif singleton_methods(false).include? _method
20
+ define_singleton_method "#{_method}_job" do |*args, **kwargs|
21
+
22
+ Eitil::SingleMethodJob.perform_later(
23
+ *args, _class: to_s, _method: _method.to_s, **kwargs
24
+ )
13
25
  end
14
- end
26
+ end
27
+ end
28
+
29
+ # BEWARE: This is an exact copy of the above method, except for .perform_now instead of .perform_later and the method's name.
30
+ # The reason for not using helper methods is to not unnecessarily fill and potentially fuck up the Kernel environment.
31
+
32
+ def new_job_debugger(_method, *args, **kwargs)
15
33
 
34
+ if instance_methods(false).include? _method
35
+ define_method "#{_method}_job_debugger" do |_self = nil, *args, **kwargs|
36
+
37
+ Eitil::SingleMethodJob.perform_now(
38
+ *args, _class: self.class.to_s, _method: _method.to_s, id: safe_send(:id), _self: self.to_json, **kwargs
39
+ )
40
+ end
41
+
42
+ elsif singleton_methods(false).include? _method
43
+ define_singleton_method "#{_method}_job_debugger" do |*args, **kwargs|
44
+
45
+ Eitil::SingleMethodJob.perform_now(
46
+ *args, _class: to_s, _method: _method.to_s, **kwargs
47
+ )
48
+ end
49
+ end
16
50
  end
17
51
 
18
52
  end
@@ -2,9 +2,23 @@ module Eitil
2
2
  class SingleMethodJob < ApplicationJob
3
3
  queue_as :default
4
4
 
5
- def perform(_class:, _method:, id: nil)
6
- object = id ? _class.constantize.find(id) : _class.constantize
7
- object.send _method
5
+ # BEWARE: _self is currently not accepted in perform_later jobs due to serialization errors
6
+
7
+ # The cases of 'id' and '_self' both handle instances, with the difference
8
+ # being that 'id' works for objects that have a database record, while '_self'
9
+ # works for non database supported instanes, such as an Exporter instance.
10
+
11
+ def perform(*args, _class:, _method:, id: nil, _self: nil, **kwargs)
12
+ object =
13
+ if id
14
+ _class.constantize.find(id)
15
+ elsif _self
16
+ _self
17
+ else
18
+ _class.constantize
19
+ end
20
+
21
+ object.send _method, *args, **kwargs
8
22
  end
9
23
  end
10
24
  end
@@ -2,59 +2,82 @@ module Eitil
2
2
  module DefaultScopes
3
3
  extend ActiveSupport::Concern
4
4
  included do
5
-
6
- SharableDateScopes = -> (column) {
7
- eitil_scope :"#{column}_today", -> { where("#{column} = ?", Date.today) }
8
- eitil_scope :"#{column}_past", -> { where("#{column} < ?", Date.today) }
9
- eitil_scope :"#{column}_future", -> { where("#{column} > ?", Date.today) }
10
-
11
- eitil_scope :"#{column}_on_date", -> (date) { where("#{column} = ?", date) }
12
- eitil_scope :"#{column}_before_date", -> (date) { where("#{column} = ?", date) }
13
- eitil_scope :"#{column}_after_date", -> (date) { where("#{column} = ?", date) }
5
+ class << self
14
6
 
15
- eitil_scope :"#{column}_between_dates", -> (from, till) { where("#{column} >= ? and #{column} <= ?", from, till) }
7
+ SharableDateScopes = -> (_class, column) {
8
+ _class.eitil_scope :"#{column}_today", -> { where("#{column} = ?", Date.today) }
9
+ _class.eitil_scope :"#{column}_past", -> { where("#{column} < ?", Date.today) }
10
+ _class.eitil_scope :"#{column}_future", -> { where("#{column} > ?", Date.today) }
11
+
12
+ _class.eitil_scope :"#{column}_on_date", -> (date) { where("#{column} = ?", date) }
13
+ _class.eitil_scope :"#{column}_before_date", -> (date) { where("#{column} = ?", date) }
14
+ _class.eitil_scope :"#{column}_after_date", -> (date) { where("#{column} = ?", date) }
15
+ _class.eitil_scope :"#{column}_between_dates", -> (from, till) { where("#{column} >= ? and #{column} <= ?", from, till) }
16
16
 
17
- eitil_scope :"#{column}_oldest_first", -> { order("#{column} ASC") }
18
- eitil_scope :"#{column}_newest_first", -> { order("#{column} DESC") }
19
- }
17
+ _class.eitil_scope :"#{column}_oldest_first", -> { order("#{column} ASC") }
18
+ _class.eitil_scope :"#{column}_newest_first", -> { order("#{column} DESC") }
19
+ }
20
20
 
21
- class << self
21
+ SharableNumScopes = -> (_class, column) {
22
+ _class.eitil_scope :"#{column}_equal_to", -> (number) { where("#{column} = ?", number) }
23
+ _class.eitil_scope :"#{column}_lower_than", -> (number) { where("#{column} = <", number) }
24
+ _class.eitil_scope :"#{column}_higher_than", -> (number) { where("#{column} = >", number) }
25
+ _class.eitil_scope :"#{column}_between", -> (min, max) { where("#{column} >= ? and #{column} <= ?", min, max) }
26
+
27
+ _class.eitil_scope :"#{column}_ascending", -> { order("#{column} ASC") }
28
+ _class.eitil_scope :"#{column}_descending", -> { order("#{column} DESC") }
29
+ }
30
+
31
+ def inherited(subclass)
32
+ super
33
+ subclass.use_eitil_scopes
34
+ end
35
+
36
+ def use_eitil_scopes
37
+ return if abstract_class?
38
+ %i[boolean datetime date integer float].each { |_type| send :"create_eitil_#{_type}_scopes" }
39
+ end
22
40
 
23
- private
41
+ def eitil_scope(_name, _proc)
42
+ scope _name, _proc unless respond_to? _name
43
+ end
44
+
45
+ def columns_of_type(data_type)
46
+ columns_hash.select { |column,v| v.sql_type_metadata.type == data_type }
47
+ end
24
48
 
25
- def use_eitil_scopes
26
- %i[boolean datetime date].each { |_type| send :"create_eitil_#{_type}_scopes" }
27
- end
49
+ def create_eitil_boolean_scopes
50
+ columns_of_type(:boolean)&.map do |column, object|
51
+ eitil_scope :"#{column}_true", -> { where(column => true) }
52
+ eitil_scope :"#{column}_false", -> { where(column => [false, nil]) }
53
+ end
54
+ end
28
55
 
29
- def eitil_scope(_name, _proc)
30
- scope _name, _proc unless respond_to? _name
31
- end
32
-
33
- def columns_of_type(data_type)
34
- columns_hash.select { |column,v| v.sql_type_metadata.type == data_type }
35
- end
56
+ def create_eitil_datetime_scopes
57
+ columns_of_type(:datetime)&.map do |column, object|
58
+ SharableDateScopes.call self, column
59
+ end
60
+ end
36
61
 
37
- def create_eitil_boolean_scopes
38
- columns_of_type(:boolean).map do |column, object|
39
- eitil_scope :"#{column}_true", -> { where(column => true) }
40
- eitil_scope :"#{column}_false", -> { where(column => [false, nil]) }
62
+ def create_eitil_date_scopes
63
+ columns_of_type(:date)&.map do |column, object|
64
+ SharableDateScopes.call self, column
65
+ end
41
66
  end
42
- end
43
67
 
44
- def create_eitil_datetime_scopes
45
- columns_of_type(:datetime).map do |column, object|
46
- SharableDateScopes.call column
68
+ def create_eitil_integer_scopes
69
+ columns_of_type(:integer)&.map do |column, object|
70
+ SharableNumScopes.call self, column
71
+ end
47
72
  end
48
- end
49
73
 
50
- def create_eitil_date_scopes
51
- columns_of_type(:date).map do |column, object|
52
- SharableDateScopes.call column
74
+ def create_eitil_float_scopes
75
+ columns_of_type(:float)&.map do |column, object|
76
+ SharableNumScopes.call self, column
77
+ end
53
78
  end
54
- end
55
79
 
56
80
  end
57
-
58
81
  end
59
82
  end
60
83
  end
data/lib/eitil/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eitil
2
- VERSION = '0.3.1'
2
+ VERSION = '0.3.6'
3
3
  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: 0.3.1
4
+ version: 0.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-04-26 00:00:00.000000000 Z
11
+ date: 2021-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,7 +52,9 @@ files:
52
52
  - app/jobs/eitil/application_job.rb
53
53
  - app/mailers/eitil/application_mailer.rb
54
54
  - app/models/eitil/application_record.rb
55
+ - config/initializers/modules/dir.rb
55
56
  - config/initializers/monkeys/application_controller.rb
57
+ - config/initializers/monkeys/application_record.rb
56
58
  - config/initializers/monkeys/date_time.rb
57
59
  - config/initializers/monkeys/hash.rb
58
60
  - config/initializers/monkeys/kernel.rb