eitil 0.3.4 → 0.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: f35510328554ac09ddfb48b697e0b7dd2b6a801b20954505b14849c2f1a3227a
4
- data.tar.gz: 9d8edf28b695b3835d4dacaf46bd1dbe7dc1e9ebcd9ae2bce403b9a12ffe7529
3
+ metadata.gz: ac7bd5bff2af923e06936b0016f4f07f8d4eba225a68dc193bdf5f277bcdbb97
4
+ data.tar.gz: 193b41fa2a5fde545b189b79a2c94328c242bf45d71ff5802cfab3fb7b95c402
5
5
  SHA512:
6
- metadata.gz: 2cec6226350e58696fb8d814d9cd7e57b768a39c5bc392d6686792d80ecc2dab328a64c131ce32bf05d49627f30b10606544e3c1a6170c4e6941054649dd931d
7
- data.tar.gz: cbb2ad53d5727feffad6007bde83d34edaf4336f47330ad95f096348f423fc0d3fca02375a3d34c38f420f9df99d30ec0f713b2436b62488879594a5e4e9bee3
6
+ metadata.gz: 52c86de08e26441922852f3cd5563a36ac46c585a3ab50745e1f0fc2dacf9dc6187574f54c7c33ba415fdd3be006e0c45b7245076b209fd74a3782b07c1ace34
7
+ data.tar.gz: 0bf06bc0226924db17b2c9b7f9138eac75116cb4d351fe9818690f2745cfaa68d43eac837dbfb0825b6870eeeb0ab4b50cb091ed05243b533501498d8ca60eac
data/README.md CHANGED
@@ -103,6 +103,22 @@ include_concerns_of(*directories, namespace: nil)
103
103
 
104
104
 
105
105
 
106
+ ## String
107
+
108
+ ```ruby
109
+ is_num?
110
+ # returns true if a string matches the Rubinius source code regex for strings and integers, false otherwise
111
+ # comes in handy since ruby plays it safe on string to number conversion ('aaa'.to_f returns 0.0, thus is valid)
112
+ # this method is also implemented for all other classes, such as Integer, Float, NilClass, TrueClass, Hash and so on...
113
+
114
+ is_nan?
115
+ # returns true if a string does NOT match the Rubinius source code regex for strings and integers, false otherwise
116
+ # comes in handy since ruby plays it safe on string to number conversion ('aaa'.to_f returns 0.0, thus is valid)
117
+ # this method is also implemented for all other classes, such as Integer, Float, NilClass, TrueClass, Hash and so on...
118
+ ```
119
+
120
+
121
+
106
122
  ## Hash
107
123
 
108
124
  ```ruby
@@ -131,6 +147,14 @@ slice_params(*args)
131
147
  self.all_associations
132
148
  # returns all associations for a given model
133
149
  # call as: Environment.all_associations
150
+
151
+ self.where_like(_hash)
152
+ # runs .where with your string field made into a wildcard and case insensitive
153
+ # call as: User.where_like(name: 'jurriaan')
154
+
155
+ self.find_by_like(_hash)
156
+ # runs .find_by with your string field made into a wildcard and case insensitive
157
+ # call as: User.find_by_like(name: 'jurriaan')
134
158
  ```
135
159
 
136
160
 
@@ -177,7 +201,7 @@ decorate(dec_item, dec_method: nil, dec_class: nil, **dec_kwargs)
177
201
  # initializers/eitil.rb
178
202
 
179
203
  Eitil.set_config do |config|
180
- config.get_controller_ivars_method = 'API::VerlofVerzoekenController.controller_ivars' # => [:user, :env]
204
+ config.get_controller_ivars_method = 'API::BaseController.controller_ivars' # => [:user, :env]
181
205
  end
182
206
  ```
183
207
 
@@ -227,14 +251,18 @@ The router wrapper is a single module which is automatically included into your
227
251
 
228
252
  ### Info
229
253
 
230
- 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.
254
+ 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.
231
255
 
232
256
  ### Job Macro
233
257
 
234
258
  ```ruby
235
- new_job(_method)
236
- # assuming a method :print_hello_world, call as: new_job :hello_world
237
- # => method :hello_world_job
259
+ new_job(_method, *args, **kwargs)
260
+ # assuming a method :hello_world, call as: new_job :hello_world
261
+ # => defines :hello_world_job
262
+
263
+ new_job_debugger(_method, *args, **kwargs)
264
+ # assuming a method :hello_world, call as: new_job_debugger :hello_world
265
+ # => defines :hello_world_job_debugger
238
266
  ```
239
267
 
240
268
  - method is
@@ -304,3 +332,50 @@ Scopes are generated through the columns of your model's database table. Which s
304
332
  Your models should inherit the module Eitil::DefaultScopes through inclusion in a superclass, such as ApplicationRecord.
305
333
 
306
334
 
335
+
336
+ # Modules & Classes
337
+
338
+
339
+
340
+ ## Eitil::Dir
341
+
342
+ ### Info
343
+
344
+ The Eitil::Dir module provides methods which help you introspect your Rails project.
345
+
346
+ ### Methods
347
+
348
+ ```ruby
349
+ Eitil::Dir.contents(directory='app')
350
+ # returns all files and subdirectories of a given directory
351
+
352
+ Eitil::Dir.files(directory='app')
353
+ # returns all files of a given directory
354
+
355
+ Eitil::Dir.subdirs(directory='app')
356
+ # returns all subdirectories of a given directory
357
+
358
+ Eitil::Dir.lines(directory='app')
359
+ # returns the total amount of lines of all files of a given directory
360
+ ```
361
+
362
+
363
+
364
+ ## Eitil::StackTrace
365
+
366
+ ### Info
367
+
368
+ The two classes Eitil::StackTrace::Stack and Eitil::StackTrace::Call, and the single module Eitil::StackTrace::Audit, provide the utility of easily viewing and storing the current stacktrace anywhere in your code. By initializing stack = Eitil::StackTrace::Stack.new, you can call methods as stack.report (returns the stacktrace as array), stack.show (pretty prints the stacktrace) and stack.find (accepts a block to find a call).
369
+
370
+ You can also store the stacktrace of a record's update action into its audit. In order to do so, you need 1) to include Eitil::StackTrace::Audit into your model, and 2) add a :stacktrace column to your audits through the following migration.
371
+
372
+ ### Migration
373
+
374
+ ```ruby
375
+ def change
376
+ add_column :audits, :stacktrace, :text, array: true, default: []
377
+ end
378
+ ```
379
+
380
+
381
+
@@ -0,0 +1,15 @@
1
+ module Eitil::StackTrace::Audit
2
+ extend ActiveSupport::Concern
3
+ included do
4
+
5
+ private
6
+
7
+ after_update :add_stacktrace_to_audit
8
+
9
+ def add_stacktrace_to_audit
10
+ stacktrace = Eitil::StackTrace::Stack.new.report
11
+ self.audits.last.update(stacktrace: stacktrace)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Eitil::StackTrace
2
+ class Call
3
+
4
+ attr_reader :program, :line, :meth
5
+
6
+ CALL_RE = /(.*):(\d+):in `(.*)'/
7
+
8
+ def initialize(string)
9
+ @program, @line, @meth = CALL_RE.match(string).captures
10
+ end
11
+
12
+ def to_s
13
+ "#{"#{meth}".ljust(50)} #{"(#{line})".ljust(6)} #{program}"
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ module Eitil::StackTrace
2
+ class Stack
3
+
4
+ attr_reader :stack, :backtrace
5
+
6
+ def initialize
7
+ @stack = caller[1..]
8
+ @backtrace = stack.map { |call| Eitil::StackTrace::Call.new(call) }
9
+ end
10
+
11
+ def report
12
+ backtrace.map(&:to_s)
13
+ end
14
+
15
+ def show
16
+ ap report
17
+ end
18
+
19
+ def find(&block)
20
+ backtrace.find(&block)
21
+ end
22
+
23
+ def self.parse(array_as_string)
24
+ array_as_string.sub('[', ' ').reverse.sub(']','').reverse.split(',').flatten
25
+ end
26
+
27
+ end
28
+ end
@@ -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
@@ -4,10 +4,24 @@ module ApplicationRecordMonkey
4
4
  extend ActiveSupport::Concern
5
5
  included do
6
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
7
+ class << self
8
+
9
+ def all_associations
10
+ reflect_on_all_associations.map do |assoc|
11
+ { assoc.name => assoc.association_class.to_s.demodulize }
12
+ end.inject &:merge
13
+ end
14
+
15
+ def where_like(_hash)
16
+ column, like = _hash.first
17
+ where("LOWER(#{column}) LIKE ?", "%#{like.downcase}%")
18
+ end
19
+
20
+ def find_by_like(_hash)
21
+ column, like = _hash.first
22
+ find_by("LOWER(#{column}) LIKE ?", "%#{like.downcase}%")
23
+ end
24
+
11
25
  end
12
26
 
13
27
  end
@@ -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
@@ -0,0 +1,96 @@
1
+ class String
2
+
3
+ # The NumberRegex belows comes from the Rubinius source code and
4
+ # identifies both integers and floats correctly.
5
+
6
+ NumberRegex = /^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/
7
+
8
+ def is_nan?
9
+ self !~ NumberRegex
10
+ end
11
+
12
+ def is_num?
13
+ !is_nan?
14
+ end
15
+
16
+ end
17
+
18
+ # Descending classes which are always numeric
19
+
20
+ class Numeric
21
+
22
+ def is_nan?
23
+ false
24
+ end
25
+
26
+ def is_num?
27
+ true
28
+ end
29
+
30
+ end
31
+
32
+ # Classes which are never numeric
33
+
34
+ class NilClass
35
+
36
+ def is_nan?
37
+ true
38
+ end
39
+
40
+ def is_num?
41
+ false
42
+ end
43
+
44
+ end
45
+
46
+
47
+ class TrueClass
48
+
49
+ def is_nan?
50
+ true
51
+ end
52
+
53
+ def is_num?
54
+ false
55
+ end
56
+
57
+ end
58
+
59
+
60
+ class FalseClass
61
+
62
+ def is_nan?
63
+ true
64
+ end
65
+
66
+ def is_num?
67
+ false
68
+ end
69
+
70
+ end
71
+
72
+
73
+ class Hash
74
+
75
+ def is_nan?
76
+ true
77
+ end
78
+
79
+ def is_num?
80
+ false
81
+ end
82
+
83
+ end
84
+
85
+
86
+ class Array
87
+
88
+ def is_nan?
89
+ true
90
+ end
91
+
92
+ def is_num?
93
+ false
94
+ end
95
+
96
+ end
@@ -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
@@ -48,7 +48,7 @@ module Eitil
48
48
 
49
49
  def create_eitil_boolean_scopes
50
50
  columns_of_type(:boolean)&.map do |column, object|
51
- eitil_scope :"#{column}_true", -> { where(column => true) }
51
+ eitil_scope :"#{column}_true", -> { where(column => true) }
52
52
  eitil_scope :"#{column}_false", -> { where(column => [false, nil]) }
53
53
  end
54
54
  end
data/lib/eitil/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Eitil
2
- VERSION = '0.3.4'
2
+ VERSION = '0.3.9'
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.4
4
+ version: 0.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-05-21 00:00:00.000000000 Z
11
+ date: 2021-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,10 @@ 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
+ - app/models/eitil/stack_trace/audit.rb
56
+ - app/models/eitil/stack_trace/call.rb
57
+ - app/models/eitil/stack_trace/stack.rb
58
+ - config/initializers/modules/dir.rb
55
59
  - config/initializers/monkeys/application_controller.rb
56
60
  - config/initializers/monkeys/application_record.rb
57
61
  - config/initializers/monkeys/date_time.rb
@@ -59,6 +63,7 @@ files:
59
63
  - config/initializers/monkeys/kernel.rb
60
64
  - config/initializers/monkeys/module.rb
61
65
  - config/initializers/monkeys/object.rb
66
+ - config/initializers/monkeys/string.rb
62
67
  - config/initializers/wrappers/decorators/application_decorator.rb
63
68
  - config/initializers/wrappers/decorators/controller_decorator.rb
64
69
  - config/initializers/wrappers/jobs/active_job_macros.rb