ephemeron 0.1.0
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 +28 -0
- data/Rakefile +29 -0
- data/lib/ephemeron.rb +98 -0
- data/lib/ephemeron/addons/controller_addons.rb +11 -0
- data/lib/ephemeron/addons/model_addons.rb +33 -0
- data/lib/ephemeron/errors.rb +12 -0
- data/lib/ephemeron/logger/convert.rb +13 -0
- data/lib/ephemeron/logger/finders.rb +24 -0
- data/lib/ephemeron/railtie.rb +6 -0
- data/lib/ephemeron/settings.rb +19 -0
- data/lib/ephemeron/store/convert.rb +24 -0
- data/lib/ephemeron/store/update.rb +20 -0
- data/lib/ephemeron/validators/before_save.rb +21 -0
- data/lib/ephemeron/validators/store.rb +14 -0
- data/lib/ephemeron/validators/store/allowed_but_unsaved.rb +21 -0
- data/lib/ephemeron/validators/store/unused.rb +25 -0
- data/lib/ephemeron/validators/store_element.rb +17 -0
- data/lib/ephemeron/version.rb +5 -0
- data/lib/ephemeron/writers/callbacks.rb +23 -0
- data/lib/ephemeron/writers/logger.rb +59 -0
- data/lib/ephemeron/writers/store.rb +66 -0
- data/lib/ephemeron/writers/thread_store.rb +9 -0
- data/lib/tasks/ephemeron_tasks.rake +5 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 032a79004b77bffee915f105cd807beb01fcc60c52e829c478fcf615a8fa8184
|
4
|
+
data.tar.gz: 65168d9788376856e6745c083f2a0d467b18deace844719e59024e9027a47db4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 88ddba6984c039180c74433d9dc9447eae247b040700f3de02c0338e6a9ffe95dc3472c7eb982b81a867044d1c214c15cafe0ede0bf9286308d15f59664e403b
|
7
|
+
data.tar.gz: 6488f41b9df17130dbedb9f1db5bfa72e1aeded337863e46fe03e898728ed6aa5dfac2666f8cdaaf7004bf0623900f1073195327e06653994d4b974a17f67f1a
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2019 Zbigniew Humeniuk
|
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,28 @@
|
|
1
|
+
# Ephemeron
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'ephemeron'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install ephemeron
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
rescue LoadError
|
6
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'rdoc/task'
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'Ephemeron'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'bundler/gem_tasks'
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
|
23
|
+
Rake::TestTask.new(:test) do |t|
|
24
|
+
t.libs << 'test'
|
25
|
+
t.pattern = 'test/**/*_test.rb'
|
26
|
+
t.verbose = false
|
27
|
+
end
|
28
|
+
|
29
|
+
task default: :test
|
data/lib/ephemeron.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ephemeron/railtie'
|
4
|
+
|
5
|
+
require 'ephemeron/addons/controller_addons'
|
6
|
+
require 'ephemeron/addons/model_addons'
|
7
|
+
|
8
|
+
require 'ephemeron/writers/thread_store'
|
9
|
+
require 'ephemeron/writers/callbacks'
|
10
|
+
require 'ephemeron/writers/logger'
|
11
|
+
require 'ephemeron/writers/store'
|
12
|
+
|
13
|
+
require 'ephemeron/errors'
|
14
|
+
require 'ephemeron/logger/convert'
|
15
|
+
require 'ephemeron/logger/finders'
|
16
|
+
require 'ephemeron/settings'
|
17
|
+
require 'ephemeron/store/convert'
|
18
|
+
require 'ephemeron/store/update'
|
19
|
+
require 'ephemeron/validators/before_save'
|
20
|
+
require 'ephemeron/validators/store'
|
21
|
+
require 'ephemeron/validators/store_element'
|
22
|
+
require 'ephemeron/validators/store/allowed_but_unsaved'
|
23
|
+
require 'ephemeron/validators/store/unused'
|
24
|
+
|
25
|
+
module Ephemeron
|
26
|
+
module_function
|
27
|
+
|
28
|
+
def configure
|
29
|
+
Ephemeron::Settings::CONFIG.new.tap do |config|
|
30
|
+
yield config
|
31
|
+
Ephemeron::Settings.configure config
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def state
|
36
|
+
Store.store
|
37
|
+
end
|
38
|
+
|
39
|
+
def logs
|
40
|
+
Logger.logs
|
41
|
+
end
|
42
|
+
|
43
|
+
def add(model, as: nil)
|
44
|
+
Store.add model, as: as
|
45
|
+
end
|
46
|
+
|
47
|
+
def proxy
|
48
|
+
Logger.log nil, :proxy_start
|
49
|
+
yield
|
50
|
+
Logger.log nil, :proxy_end
|
51
|
+
end
|
52
|
+
|
53
|
+
def get(key)
|
54
|
+
Store.get key
|
55
|
+
end
|
56
|
+
|
57
|
+
def used(model_s)
|
58
|
+
log_used = ->(model) { Logger.log model, :used }
|
59
|
+
if model_s.is_a? ActiveRecord::Base
|
60
|
+
log_used.call model_s
|
61
|
+
else
|
62
|
+
model_s.each(&log_used)
|
63
|
+
end
|
64
|
+
model_s
|
65
|
+
end
|
66
|
+
|
67
|
+
def allow_save!(model)
|
68
|
+
model.tap { |m| Logger.log m, :save_allowed }
|
69
|
+
end
|
70
|
+
|
71
|
+
def skip_save!(model)
|
72
|
+
Logger.log model, :skip_save
|
73
|
+
end
|
74
|
+
|
75
|
+
def after_save!(&block)
|
76
|
+
Callbacks.add block
|
77
|
+
end
|
78
|
+
|
79
|
+
def finish
|
80
|
+
if Store.aliases[nil] != :abort
|
81
|
+
Store.validate
|
82
|
+
Store.persist
|
83
|
+
Callbacks.call
|
84
|
+
end
|
85
|
+
reset
|
86
|
+
end
|
87
|
+
|
88
|
+
def stop
|
89
|
+
Store.aliases[nil] = :abort
|
90
|
+
end
|
91
|
+
|
92
|
+
def reset
|
93
|
+
Store.reset
|
94
|
+
Logger.reset
|
95
|
+
Callbacks.reset
|
96
|
+
true
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
module ModelAddons
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
after_find lambda { |model|
|
9
|
+
Ephemeron.add model
|
10
|
+
}
|
11
|
+
|
12
|
+
after_validation lambda { |model|
|
13
|
+
Logger.log model, :used, soft: true
|
14
|
+
}
|
15
|
+
|
16
|
+
before_save lambda { |model|
|
17
|
+
Validators::BeforeSave.call model
|
18
|
+
}
|
19
|
+
|
20
|
+
after_create lambda { |model|
|
21
|
+
Store::Update.call model
|
22
|
+
}
|
23
|
+
|
24
|
+
after_save lambda { |model|
|
25
|
+
Logger.log model, :saved
|
26
|
+
}
|
27
|
+
|
28
|
+
after_destroy lambda { |model|
|
29
|
+
Ephemeron::Store.destroy model
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Logger
|
5
|
+
module Finders
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def find_all_events_for(model, *events)
|
9
|
+
Logger.logs
|
10
|
+
.filter { |l| events.any? { |e| l == Logger::Convert.call(model, e) } }
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_first_allowed_but_unsaved
|
14
|
+
ary = Logger.logs
|
15
|
+
.reverse
|
16
|
+
.map { |line| line.split ' ' }
|
17
|
+
.find { |arr| %w[save_allowed saved].include?(arr[1]) }
|
18
|
+
return nil if ary.nil? || ary[1] == 'saved'
|
19
|
+
|
20
|
+
Store.store[ary[0]]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Settings
|
5
|
+
CONFIG = Struct.new :skip_models
|
6
|
+
|
7
|
+
class << self
|
8
|
+
attr_writer :skipped_models
|
9
|
+
|
10
|
+
def skipped_models
|
11
|
+
@skipped_models || []
|
12
|
+
end
|
13
|
+
|
14
|
+
def configure(config)
|
15
|
+
Ephemeron::Settings.skipped_models = config.skip_models
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Store
|
5
|
+
class Convert
|
6
|
+
class << self
|
7
|
+
def call(model_s, as_new_record: false)
|
8
|
+
return class_name_and_id(model_s, as_new_record) if model_s.is_a?(ActiveRecord::Base)
|
9
|
+
|
10
|
+
model_s.map { |model| class_name_and_id(model) }.join ', '
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def class_name_and_id(model, as_new_record = false)
|
16
|
+
new_record = as_new_record || model.new_record?
|
17
|
+
name = model.class.name.downcase
|
18
|
+
id = new_record ? "new_record##{model.object_id}" : model.id
|
19
|
+
"#{name}##{id}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Store
|
5
|
+
module Update
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def call(model)
|
9
|
+
return unless Store.has? model, as_new_record: true
|
10
|
+
|
11
|
+
Store.add model
|
12
|
+
Store.store.delete Convert.call(model, as_new_record: true)
|
13
|
+
|
14
|
+
Store.aliases.find_all { |_, v| v == Convert.call(model, as_new_record: true) }
|
15
|
+
.to_h.keys
|
16
|
+
.each { |key| Store.aliases[key] = Convert.call(model) }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
module Validators
|
5
|
+
module BeforeSave
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def call(model)
|
9
|
+
return unless Ephemeron::Store.has? model
|
10
|
+
|
11
|
+
last_event = Ephemeron::Logger::Finders
|
12
|
+
.find_all_events_for(model, :save_allowed, :saved)
|
13
|
+
.last
|
14
|
+
return if last_event == Logger::Convert.call(model, :save_allowed)
|
15
|
+
|
16
|
+
msg = "prior persistence for #{Ephemeron::Store::Convert.call(model)} is prohibited"
|
17
|
+
raise(PersistenceError, msg)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
module Validators
|
5
|
+
module Store
|
6
|
+
module AllowedButUnsaved
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def call
|
10
|
+
model = Ephemeron::Logger::Finders.find_first_allowed_but_unsaved
|
11
|
+
return if model.nil?
|
12
|
+
|
13
|
+
raise(
|
14
|
+
PersistenceError,
|
15
|
+
"save allowed for #{Ephemeron::Store::Convert.call(model)} but never saved"
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
module Validators
|
5
|
+
module Store
|
6
|
+
module Unused
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def call
|
10
|
+
models = Ephemeron::Store
|
11
|
+
.store
|
12
|
+
.filter { |_, model| !model.changed? && !Logger.has?(model, :used) }
|
13
|
+
.values
|
14
|
+
return if models.empty?
|
15
|
+
|
16
|
+
model_ids = Ephemeron::Store::Convert.call(models)
|
17
|
+
raise(
|
18
|
+
StoreError,
|
19
|
+
"#{model_ids} were added to store but neither fetched nor changed"
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
module Validators
|
5
|
+
module StoreElement
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def call(model)
|
9
|
+
return false if Logger.logs.last == Logger::Convert.call(nil, :proxy_start)
|
10
|
+
return false unless model.is_a?(ActiveRecord::Base)
|
11
|
+
return false if Settings.skipped_models.include? model.class.name
|
12
|
+
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Callbacks < ThreadStore
|
5
|
+
attribute :ts_after_save_callbacks
|
6
|
+
|
7
|
+
def after_save_callbacks
|
8
|
+
self.ts_after_save_callbacks ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(callback)
|
12
|
+
after_save_callbacks << callback
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
after_save_callbacks.each(&:call)
|
17
|
+
end
|
18
|
+
|
19
|
+
def reset
|
20
|
+
self.ts_after_save_callbacks = []
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Logger < ThreadStore
|
5
|
+
attribute :ts_logs
|
6
|
+
|
7
|
+
PROXY_EVENTS = %i[proxy_start proxy_end].freeze
|
8
|
+
VALID_EVENTS = %i[saved save_allowed skip_save used] + PROXY_EVENTS
|
9
|
+
|
10
|
+
def logs
|
11
|
+
self.ts_logs ||= []
|
12
|
+
end
|
13
|
+
|
14
|
+
def has?(model, event)
|
15
|
+
validate model, event
|
16
|
+
logs.include? Convert.call(model, event)
|
17
|
+
end
|
18
|
+
|
19
|
+
def log(model, event, soft: false)
|
20
|
+
validate model, event
|
21
|
+
logs << Convert.call(model, event)
|
22
|
+
rescue LoggerError, StoreError => e
|
23
|
+
raise e unless soft
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset
|
27
|
+
self.ts_logs = []
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def validate(model, event)
|
33
|
+
raise(LoggerError, "event (#{event}) is invalid") if VALID_EVENTS.exclude?(event)
|
34
|
+
return true if validate_proxy_events model, event
|
35
|
+
|
36
|
+
raise(StoreError, "can't #{event_name_for_validate event} for nil") if model.nil?
|
37
|
+
return true if Store.has?(model)
|
38
|
+
return true if event == :saved
|
39
|
+
|
40
|
+
raise StoreError, "can't #{event_name_for_validate event} " \
|
41
|
+
"if #{Store::Convert.call model} is not in store"
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_proxy_events(model, event)
|
45
|
+
return false if PROXY_EVENTS.exclude?(event)
|
46
|
+
return true if model.nil?
|
47
|
+
|
48
|
+
raise LoggerError, 'Proxy events can be logged for nil only'
|
49
|
+
end
|
50
|
+
|
51
|
+
def event_name_for_validate(event)
|
52
|
+
if event == :used
|
53
|
+
'mark as used'
|
54
|
+
else
|
55
|
+
'log'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ephemeron
|
4
|
+
class Store < ThreadStore
|
5
|
+
attribute :ts_store, :ts_aliases
|
6
|
+
|
7
|
+
def store
|
8
|
+
self.ts_store ||= {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def aliases
|
12
|
+
self.ts_aliases ||= {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def has?(model, as_new_record: false)
|
16
|
+
!store[Convert.call(model, as_new_record: as_new_record)].nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(model, as: nil)
|
20
|
+
return unless Validators::StoreElement.call(model)
|
21
|
+
|
22
|
+
key = Convert.call model
|
23
|
+
in_store = !store[key].nil?
|
24
|
+
store[key] = model unless in_store
|
25
|
+
if !as.nil?
|
26
|
+
aliases[as] = key
|
27
|
+
elsif in_store
|
28
|
+
raise StoreError, "#{key} is already in the store"
|
29
|
+
end
|
30
|
+
model
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(key)
|
34
|
+
store[aliases[key]].tap do |model|
|
35
|
+
Logger.log(model, :used) if model
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate
|
40
|
+
Validators::Store.call
|
41
|
+
end
|
42
|
+
|
43
|
+
def persist
|
44
|
+
changed_models = store.filter { |_, v| v.changed? }.values
|
45
|
+
.filter { |model| !Logger.has?(model, :skip_save) }
|
46
|
+
ActiveRecord::Base.transaction do
|
47
|
+
changed_models.each do |model|
|
48
|
+
Ephemeron.allow_save! model
|
49
|
+
model.save!
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def destroy(model)
|
55
|
+
key = Convert.call model
|
56
|
+
return if store[key].nil?
|
57
|
+
|
58
|
+
store.delete key
|
59
|
+
end
|
60
|
+
|
61
|
+
def reset
|
62
|
+
self.ts_store = {}
|
63
|
+
self.ts_aliases = {}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ephemeron
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zbigniew Humeniuk
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-01-14 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.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: jb
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 0.7.0
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.7.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec-mocks
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.9'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '3.9'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: sqlite3
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
description: |
|
76
|
+
Ephemeron improves the performance of your app.
|
77
|
+
It takes on itself the persistence of the ActiveRecord objects.
|
78
|
+
It protects you from saving the same object many times.
|
79
|
+
It checks whether a fetched from a database object was used.
|
80
|
+
It allows you to eliminate the controller's before_actions that are unnecessarily called.
|
81
|
+
Ephemeron works in the context of the thread and does the bulk of its job (i.a. persistence) at the end of the thread's lifecycle.
|
82
|
+
Although, you can trigger the finalization at any given moment.
|
83
|
+
You don't have to make a distinction in the code for the part that is responsible for the domain logic and the other responsible for the application layers.
|
84
|
+
email:
|
85
|
+
- hello@artofcode.co
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- MIT-LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- lib/ephemeron.rb
|
94
|
+
- lib/ephemeron/addons/controller_addons.rb
|
95
|
+
- lib/ephemeron/addons/model_addons.rb
|
96
|
+
- lib/ephemeron/errors.rb
|
97
|
+
- lib/ephemeron/logger/convert.rb
|
98
|
+
- lib/ephemeron/logger/finders.rb
|
99
|
+
- lib/ephemeron/railtie.rb
|
100
|
+
- lib/ephemeron/settings.rb
|
101
|
+
- lib/ephemeron/store/convert.rb
|
102
|
+
- lib/ephemeron/store/update.rb
|
103
|
+
- lib/ephemeron/validators/before_save.rb
|
104
|
+
- lib/ephemeron/validators/store.rb
|
105
|
+
- lib/ephemeron/validators/store/allowed_but_unsaved.rb
|
106
|
+
- lib/ephemeron/validators/store/unused.rb
|
107
|
+
- lib/ephemeron/validators/store_element.rb
|
108
|
+
- lib/ephemeron/version.rb
|
109
|
+
- lib/ephemeron/writers/callbacks.rb
|
110
|
+
- lib/ephemeron/writers/logger.rb
|
111
|
+
- lib/ephemeron/writers/store.rb
|
112
|
+
- lib/ephemeron/writers/thread_store.rb
|
113
|
+
- lib/tasks/ephemeron_tasks.rake
|
114
|
+
homepage: https://artofcode.co
|
115
|
+
licenses:
|
116
|
+
- MIT
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
requirements: []
|
133
|
+
rubygems_version: 3.1.2
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: The organic DDD
|
137
|
+
test_files: []
|