eitil 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +272 -0
- data/Rakefile +18 -0
- data/app/controllers/eitil/application_controller.rb +4 -0
- data/app/jobs/eitil/application_job.rb +4 -0
- data/app/mailers/eitil/application_mailer.rb +6 -0
- data/app/models/eitil/application_record.rb +5 -0
- data/config/initializers/monkeys/application_controller.rb +14 -0
- data/config/initializers/monkeys/date_time.rb +7 -0
- data/config/initializers/monkeys/hash.rb +14 -0
- data/config/initializers/monkeys/kernel.rb +44 -0
- data/config/initializers/monkeys/module.rb +12 -0
- data/config/initializers/monkeys/object.rb +29 -0
- data/config/initializers/wrappers/decorators/application_decorator.rb +19 -0
- data/config/initializers/wrappers/decorators/controller_decorator.rb +63 -0
- data/config/initializers/wrappers/jobs/active_job_macros.rb +18 -0
- data/config/initializers/wrappers/jobs/single_method_job.rb +10 -0
- data/config/initializers/wrappers/routes/extended_resources.rb +40 -0
- data/config/initializers/wrappers/scopes/default_scopes.rb +60 -0
- data/config/routes.rb +2 -0
- data/lib/eitil.rb +6 -0
- data/lib/eitil/engine.rb +14 -0
- data/lib/eitil/version.rb +3 -0
- data/lib/tasks/eitil_tasks.rake +4 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f822863c972553dc89dca4e80fce4b197c89c27f78456342195f46b920fa07f5
|
4
|
+
data.tar.gz: 0e852adfd5a9127d3d67f349102bb6000121b730a5a42d0628b09beab45723fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cc64496f6e70c4d737ddf6bf091988ab01425802852034dd1d0c083bee1cda38ee25381927b498fc74c0094f27c071b71e10b360fc00ac477e81635b509d1915
|
7
|
+
data.tar.gz: ac2c18d0bd040e892caf008de55550cd09322fb69b09d15efd6adf6d147ce399b8e5aff547603af1311c7ebb86f0a8051da40211791d70042ee4e87a57ef23b3
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2021 Jurriaan Schrofer
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,272 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
# Eitil (Eitje Util)
|
5
|
+
|
6
|
+
Never stops increasing your life's efficacy and productivity, yay!
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
|
16
|
+
gem 'eitil', git: 'https://github.com/eitje-app/eitil_engine', branch: 'production'
|
17
|
+
|
18
|
+
```
|
19
|
+
|
20
|
+
Or this line, with your own path correctly set, for development purposes:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
|
24
|
+
gem 'eitil', path: "/Users/jurriaanschrofer/Documents/eitil"
|
25
|
+
|
26
|
+
```
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
# Monkey patches
|
31
|
+
|
32
|
+
|
33
|
+
|
34
|
+
## Kernel
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
all_args_to_ivars(binding)
|
38
|
+
# sets all keywords arguments of the method's local binding to instance variables
|
39
|
+
# call as: all_args_to_ivars binding
|
40
|
+
|
41
|
+
args_to_ivars(binding, *local_vars)
|
42
|
+
# sets specified keywords arguments of the method's local binding to instance variables
|
43
|
+
# call as: all_args_to_ivars binding :user_id, :user_name
|
44
|
+
|
45
|
+
all_kwargs_to_ivars(binding)
|
46
|
+
# sets the method's **kwargs argument to instance variables, with each key as the ivar's "@#{name}" and the value as its value
|
47
|
+
# call as: kwargs_to_ivars binding
|
48
|
+
|
49
|
+
set_ivars(*ivars)
|
50
|
+
# sets instance variables named @"#{ivar}" for each symbol passed, by invoking send("set_#{ivar}")
|
51
|
+
# e.g. set_ivars(:user) sets @user with the value returned by your local method .set_user
|
52
|
+
# call as: set_ivars :user, :authentication, :connection
|
53
|
+
|
54
|
+
safe_send(method, *args, return_value: nil)
|
55
|
+
# a safe version of .send, which in case of an error rescues and returns return_value (default: nil) instead
|
56
|
+
|
57
|
+
safe_call(*args, return_value: nil, &block)
|
58
|
+
# a safe version of .call, which in case of an error rescues and returns return_value (default: nil) instead
|
59
|
+
# accepts either a proc argument or a block
|
60
|
+
|
61
|
+
raise_error(_class_name, message = nil)
|
62
|
+
# creates an error class if currently undefined, inheriting from StandardError, and raises the error with the given message
|
63
|
+
# call as: raise_error "SomethingWentWrongError", "check your code, bro!"
|
64
|
+
# => SomethingWentWrongError (check your code, bro!)
|
65
|
+
```
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
## Object
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
all_methods(include_ancestors = true, grep: nil)
|
73
|
+
# pretty prints all methods for any object, grouped per type (e.g. private_methods, public_instance_methods)
|
74
|
+
# call as: Class.all_methods false, grep: /json/
|
75
|
+
```
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
## Module
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
include_concerns_of(*directories)
|
83
|
+
# includes all models/concerns/{sub_directory}/* within a module or class
|
84
|
+
# call as: include_concerns_of :user, :mail
|
85
|
+
# => includes all modules of models/concerns/user/* and models/oncerns/mail/*
|
86
|
+
```
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
## Hash
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
auto_dig(_hash = self, _key)
|
94
|
+
# finds the value for the given hash key, irregardless of the amount of nested layers
|
95
|
+
# call as: {a: 1, b: {c: 2, d: {e: 3}}}.auto_dig :e
|
96
|
+
# => 3
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
## ApplicationController
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
slice_params(*args)
|
105
|
+
# slices request params, converts them to JSON and symbolizes the keys
|
106
|
+
# call as: slice_params :id, :user
|
107
|
+
# => { id: 1, user: 69 }
|
108
|
+
```
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
## DateTime
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
prettify
|
116
|
+
# formats DateTime instances into a pretty, simple and filename friendly format
|
117
|
+
# call as: DateTime.now.prettify
|
118
|
+
# => "2021-04-21.17:51:42"
|
119
|
+
```
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
# Wrappers
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
## Decorators
|
128
|
+
|
129
|
+
### Info
|
130
|
+
|
131
|
+
The Eitil decorator wrappers help you to standardize the calling of the right decorator method from within your controller action. Basically it provides you with a decorate macro in each controller.
|
132
|
+
|
133
|
+
### Decorate Macro
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
decorate(dec_item, dec_method: nil, dec_class: nil, **dec_kwargs)
|
137
|
+
```
|
138
|
+
|
139
|
+
- dec_item is the instance that will be decorated
|
140
|
+
- dec_method enabled you to set the desired decorator method. If not provided, it will look into the request params: if params["isMobile"] is present it will call .app, if params["isWeb"] is present it will call :app. If neither is provided in the params, it will call the default method :base.
|
141
|
+
- dec_class enables you to overwrite the decorator class that will be called. If not provided, the decorator class will be inferred from the instance model's classname (User => UserDecorator).
|
142
|
+
- dec_kwargs enables you to provide additional arguments, which will be passed to your decorator method.
|
143
|
+
|
144
|
+
### Configuration
|
145
|
+
|
146
|
+
1. Your decorator classes should inherit from Eitil::ApplicationDecorator.
|
147
|
+
2. Your controllers should inherit the module Eitil::ControllerDecorator, through inclusion in a superclass.
|
148
|
+
3. If you set controller ivars for each request, you can make them available in your decorators by providing Eitil a method which returns the names of your ivars as an array of symbols:
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
# initializers/eitil.rb
|
152
|
+
|
153
|
+
Eitil.set_config do |config|
|
154
|
+
config.get_controller_ivars_method = 'API::VerlofVerzoekenController.controller_ivars' # => [:user, :env]
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
|
159
|
+
|
160
|
+
## Router
|
161
|
+
|
162
|
+
### Info
|
163
|
+
|
164
|
+
The Eitil router wrapper enables you to easily create new routes that can be shared among controllers. In that sense, it is as a custom extension of the built-in resourceful routes.
|
165
|
+
|
166
|
+
### Create New Route Macro
|
167
|
+
|
168
|
+
The first macro, new_route, enables you to create new route objects which may be called and used by different controllers.
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
# config/routes.rb
|
172
|
+
|
173
|
+
new_route(verb, _method, action, scope)
|
174
|
+
# call as: new_route :post, :attachment, "add_attachment", :member
|
175
|
+
```
|
176
|
+
|
177
|
+
- verb refers to the http_verb, e.g. :put.
|
178
|
+
- method refers to the given http method (e.g. 'users/:id'). Additionally, this is the name you will refer to in order to include the route into a controller. Therefore the argument should be unique among all other routes.
|
179
|
+
- action refers to the controller action to which you want to redirect to request, e.g. :update_user.
|
180
|
+
- scope refers to the url and can be set to either :member or :collection.
|
181
|
+
|
182
|
+
### Add Routes Macro
|
183
|
+
|
184
|
+
The second macro, extended_resources, enables you to create all standard resources for a controller and add your own standardized routes. This macro works the same as the built-in :resources, except that you can pass more arguments to only: [], which adds the routes to your controller.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
# config/routes.rb
|
188
|
+
|
189
|
+
extended_resources(controller, **kwargs)
|
190
|
+
# call as: extended_resources :posts, only: [:create, :update, :attachment]
|
191
|
+
|
192
|
+
```
|
193
|
+
|
194
|
+
### Configuration
|
195
|
+
|
196
|
+
The router wrapper is a single module which is automatically included into your application's router file, therefore no configuration is required.
|
197
|
+
|
198
|
+
|
199
|
+
|
200
|
+
## Jobs
|
201
|
+
|
202
|
+
### Info
|
203
|
+
|
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.
|
205
|
+
|
206
|
+
### Job Macro
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
new_job(_method)
|
210
|
+
# assuming a method :print_hello_world, call as: new_job :hello_world
|
211
|
+
# => method :hello_world_job
|
212
|
+
```
|
213
|
+
|
214
|
+
- method is
|
215
|
+
|
216
|
+
### Configuration
|
217
|
+
|
218
|
+
The new_job macro is monkey patched into Kernel, therefore no configuration is required.
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
## Scopes
|
223
|
+
|
224
|
+
### Info
|
225
|
+
|
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
|
+
```
|
235
|
+
|
236
|
+
### The Scopes
|
237
|
+
|
238
|
+
Scopes are generated through the columns of your model's database table. Which scopes are generated depends on the datatype of a column. For example, if your User model with table users has a column is_manager, a scope :is_manager_true is generated for your User model. A scope method is defined only if it does not already responds to another method of the same name. The scopes generated are:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
# columns of datatype: boolean
|
242
|
+
.{column_name}_true
|
243
|
+
.{column_name}_false
|
244
|
+
|
245
|
+
# columns of datatype: datetime
|
246
|
+
.{column_name}_today
|
247
|
+
.{column_name}_past
|
248
|
+
.{column_name}_future
|
249
|
+
.{column_name}_on_date(date)
|
250
|
+
.{column_name}_before_date(date)
|
251
|
+
.{column_name}_after_date(date)
|
252
|
+
.{column_name}_between_dates(start_date, end_date)
|
253
|
+
.{column_name}_oldest_first
|
254
|
+
.{column_name}_newest_first
|
255
|
+
|
256
|
+
# columns of datatype: date
|
257
|
+
.{column_name}_today
|
258
|
+
.{column_name}_past
|
259
|
+
.{column_name}_future
|
260
|
+
.{column_name}_on_date(date)
|
261
|
+
.{column_name}_before_date(date)
|
262
|
+
.{column_name}_after_date(date)
|
263
|
+
.{column_name}_between_dates(start_date, end_date)
|
264
|
+
.{column_name}_oldest_first
|
265
|
+
.{column_name}_newest_first
|
266
|
+
```
|
267
|
+
|
268
|
+
### Configuration
|
269
|
+
|
270
|
+
Your models should inherit the module Eitil::DefaultScopes through inclusion in a superclass, such as ApplicationRecord.
|
271
|
+
|
272
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
|
3
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
4
|
+
load "rails/tasks/engine.rake"
|
5
|
+
|
6
|
+
load "rails/tasks/statistics.rake"
|
7
|
+
|
8
|
+
require "bundler/gem_tasks"
|
9
|
+
|
10
|
+
require "rake/testtask"
|
11
|
+
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'test'
|
14
|
+
t.pattern = 'test/**/*_test.rb'
|
15
|
+
t.verbose = false
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: :test
|
@@ -0,0 +1,44 @@
|
|
1
|
+
Kernel.module_eval do
|
2
|
+
|
3
|
+
def all_args_to_ivars(local_binding)
|
4
|
+
local_binding.local_variables.each do |lvar|
|
5
|
+
instance_variable_set("@#{lvar}", local_binding.local_variable_get(lvar))
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def args_to_ivars(local_binding, *local_vars)
|
10
|
+
local_vars.each do |lvar|
|
11
|
+
instance_variable_set("@#{lvar}", local_binding.local_variable_get(lvar))
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def all_kwargs_to_ivars(local_binding)
|
16
|
+
local_binding.local_variable_get(:kwargs).each do |name, value|
|
17
|
+
instance_variable_set "@#{name}", value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_ivars(*ivars)
|
22
|
+
ivars.each do |ivar|
|
23
|
+
instance_variable_set("@#{ivar}", send("set_#{ivar}"))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def safe_call(*args, return_value: nil, &block)
|
28
|
+
block.call self, *args
|
29
|
+
rescue
|
30
|
+
return_value
|
31
|
+
end
|
32
|
+
|
33
|
+
def safe_send(method, *args, return_value: nil)
|
34
|
+
self.send method, *args
|
35
|
+
rescue
|
36
|
+
return_value
|
37
|
+
end
|
38
|
+
|
39
|
+
def raise_error(_class_name, message = nil)
|
40
|
+
Object.const_set(_class_name, Class.new(StandardError)) unless Object.const_defined?(_class_name)
|
41
|
+
raise _class_name.constantize.new message
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Module
|
2
|
+
|
3
|
+
def include_concerns_of(*directories)
|
4
|
+
directories.map! { |dir| dir.to_s.camelcase }
|
5
|
+
|
6
|
+
directories.each do |dir|
|
7
|
+
konstants = dir.constantize.constants(false)
|
8
|
+
konstants.each { |kon| include(const_get "#{dir}::#{kon}") }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "awesome_print"
|
2
|
+
|
3
|
+
class Object
|
4
|
+
|
5
|
+
def all_methods(include_ancestors = true, grep: nil)
|
6
|
+
|
7
|
+
_introspection_methods = %i$
|
8
|
+
methods
|
9
|
+
singleton_methods
|
10
|
+
instance_methods
|
11
|
+
private_methods
|
12
|
+
public_methods
|
13
|
+
protected_methods
|
14
|
+
private_instance_methods
|
15
|
+
public_instance_methods
|
16
|
+
protected_instance_methods
|
17
|
+
$
|
18
|
+
|
19
|
+
_introspection_methods.map! do |_m|
|
20
|
+
_methods = safe_send _m, include_ancestors
|
21
|
+
_methods = grep ? _methods&.grep(grep) : _methods
|
22
|
+
{ _m => _methods }
|
23
|
+
end
|
24
|
+
|
25
|
+
ap _introspection_methods.inject &:merge
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Eitil
|
2
|
+
class ApplicationDecorator
|
3
|
+
|
4
|
+
include ActiveModel::Model
|
5
|
+
|
6
|
+
def initialize(attributes={}, **kwargs)
|
7
|
+
super attributes
|
8
|
+
all_kwargs_to_ivars binding
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.method_missing(method_name, *args, **kwargs)
|
12
|
+
if %i$ web app $.include?(method_name.to_sym)
|
13
|
+
kwargs.any? ? send(:base, *args, **kwargs) : send(:base, *args)
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Eitil
|
2
|
+
module ControllerDecorator
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def decorate(dec_item, dec_method: nil, dec_class: nil, **dec_kwargs)
|
9
|
+
all_args_to_ivars binding
|
10
|
+
set_ivars :dec_class, :dec_method, :decorator
|
11
|
+
send_to_decorator
|
12
|
+
end
|
13
|
+
|
14
|
+
def send_to_decorator
|
15
|
+
@dec_kwargs.any? ? @decorator.send(@dec_method, @dec_item, @dec_kwargs)
|
16
|
+
: @decorator.send(@dec_method, @dec_item)
|
17
|
+
|
18
|
+
rescue NoMethodError => e
|
19
|
+
inform_no_method_for_decorator_error
|
20
|
+
@dec_item
|
21
|
+
end
|
22
|
+
|
23
|
+
def inform_no_method_for_decorator_error
|
24
|
+
message = "Warning: NoMethodError for #{@dec_class}.#{@dec_method}, returned @dec_item instead."
|
25
|
+
Logger.new("#{Rails.root}/log/decorator_log.log").warn message
|
26
|
+
warn message
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_dec_method
|
30
|
+
@dec_method = @dec_method || derived_dec_method || :base
|
31
|
+
end
|
32
|
+
|
33
|
+
def derived_dec_method
|
34
|
+
return unless respond_to? :params
|
35
|
+
return :app if params["isMobile"]
|
36
|
+
return :web if params["isWeb"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_dec_class
|
40
|
+
@dec_class = @dec_class ? manual_set_dec_class : derived_dec_class
|
41
|
+
end
|
42
|
+
|
43
|
+
def manual_set_dec_class
|
44
|
+
"#{@dec_class}Decorator".constantize
|
45
|
+
end
|
46
|
+
|
47
|
+
def derived_dec_class
|
48
|
+
"#{@dec_item.class.name}Decorator".constantize
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_decorator
|
52
|
+
@decorator = @dec_class.new controller_ivars
|
53
|
+
end
|
54
|
+
|
55
|
+
def controller_ivars
|
56
|
+
eval(Eitil.get_controller_ivars_method).map do |ivar|
|
57
|
+
{ ivar => instance_variable_get("@#{ivar.to_s}") }
|
58
|
+
end.inject &:merge
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Kernel.module_eval do
|
2
|
+
|
3
|
+
def new_job(_method)
|
4
|
+
|
5
|
+
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)
|
8
|
+
end
|
9
|
+
|
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)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Eitil
|
2
|
+
module ExtendedResources
|
3
|
+
|
4
|
+
RESOURCEFUL_ACTIONS = %i$ index new create show edit update destroy $
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def extended_resources(controller, **kwargs)
|
9
|
+
all_args_to_ivars binding
|
10
|
+
|
11
|
+
resources(controller, **resource_args) do
|
12
|
+
extended_routes&.each { |route| send(route).call controller }
|
13
|
+
yield if block_given?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def resource_args
|
18
|
+
duplicate = @kwargs.dup
|
19
|
+
duplicate[:only] = resourceful_routes
|
20
|
+
duplicate
|
21
|
+
end
|
22
|
+
|
23
|
+
def resourceful_routes
|
24
|
+
@kwargs.dig(:only) - extended_routes
|
25
|
+
end
|
26
|
+
|
27
|
+
def extended_routes
|
28
|
+
@kwargs.dig(:only) - RESOURCEFUL_ACTIONS
|
29
|
+
end
|
30
|
+
|
31
|
+
def new_route(verb, _method, action, scope)
|
32
|
+
self.class.send :define_method, _method do
|
33
|
+
-> (controller) { send(verb, _method, to: "#{controller}##{action}", on: scope) }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
ActionDispatch::Routing::Mapper.__send__ :include, Eitil::ExtendedResources
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Eitil
|
2
|
+
module DefaultScopes
|
3
|
+
extend ActiveSupport::Concern
|
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) }
|
14
|
+
|
15
|
+
eitil_scope :"#{column}_between_dates", -> (from, till) { where("#{column} >= ? and #{column} <= ?", from, till) }
|
16
|
+
|
17
|
+
eitil_scope :"#{column}_oldest_first", -> { order("#{column} ASC") }
|
18
|
+
eitil_scope :"#{column}_newest_first", -> { order("#{column} DESC") }
|
19
|
+
}
|
20
|
+
|
21
|
+
class << self
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def use_eitil_scopes
|
26
|
+
%i[boolean datetime date].each { |_type| send :"create_eitil_#{_type}_scopes" }
|
27
|
+
end
|
28
|
+
|
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
|
36
|
+
|
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]) }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_eitil_datetime_scopes
|
45
|
+
columns_of_type(:datetime).map do |column, object|
|
46
|
+
SharableDateScopes.call column
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def create_eitil_date_scopes
|
51
|
+
columns_of_type(:date).map do |column, object|
|
52
|
+
SharableDateScopes.call column
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/config/routes.rb
ADDED
data/lib/eitil.rb
ADDED
data/lib/eitil/engine.rb
ADDED
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: eitil
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jurriaan Schrofer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.2.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.2.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: awesome_print
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.9.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.9.2
|
41
|
+
description: Description of Eitil.
|
42
|
+
email:
|
43
|
+
- jschrofer@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- MIT-LICENSE
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- app/controllers/eitil/application_controller.rb
|
52
|
+
- app/jobs/eitil/application_job.rb
|
53
|
+
- app/mailers/eitil/application_mailer.rb
|
54
|
+
- app/models/eitil/application_record.rb
|
55
|
+
- config/initializers/monkeys/application_controller.rb
|
56
|
+
- config/initializers/monkeys/date_time.rb
|
57
|
+
- config/initializers/monkeys/hash.rb
|
58
|
+
- config/initializers/monkeys/kernel.rb
|
59
|
+
- config/initializers/monkeys/module.rb
|
60
|
+
- config/initializers/monkeys/object.rb
|
61
|
+
- config/initializers/wrappers/decorators/application_decorator.rb
|
62
|
+
- config/initializers/wrappers/decorators/controller_decorator.rb
|
63
|
+
- config/initializers/wrappers/jobs/active_job_macros.rb
|
64
|
+
- config/initializers/wrappers/jobs/single_method_job.rb
|
65
|
+
- config/initializers/wrappers/routes/extended_resources.rb
|
66
|
+
- config/initializers/wrappers/scopes/default_scopes.rb
|
67
|
+
- config/routes.rb
|
68
|
+
- lib/eitil.rb
|
69
|
+
- lib/eitil/engine.rb
|
70
|
+
- lib/eitil/version.rb
|
71
|
+
- lib/tasks/eitil_tasks.rake
|
72
|
+
homepage: https://eitje.app
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
metadata:
|
76
|
+
homepage_uri: https://eitje.app
|
77
|
+
source_code_uri: https://eitje.app
|
78
|
+
changelog_uri: https://eitje.app
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubygems_version: 3.1.2
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: Summary of Eitil.
|
98
|
+
test_files: []
|