midnight-rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/abc.js +14 -0
- data/lib/midnight/rails.rb +20 -0
- data/lib/midnight/rails/active_record_event_adapter.rb +47 -0
- data/lib/midnight/rails/active_record_interactor.rb +70 -0
- data/lib/midnight/rails/active_record_wrapper.rb +55 -0
- data/lib/midnight/rails/command.rb +13 -0
- data/lib/midnight/rails/commit_hooker.rb +28 -0
- data/lib/midnight/rails/default_event.rb +7 -0
- data/lib/midnight/rails/default_migration.rb +83 -0
- data/lib/midnight/rails/default_state.rb +7 -0
- data/lib/midnight/rails/dry_event.rb +29 -0
- data/lib/midnight/rails/stale_object_error.rb +10 -0
- data/lib/midnight/rails/state_adapter.rb +56 -0
- data/lib/midnight/rails/version.rb +5 -0
- metadata +155 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 535ce5a0b745470d77c89d9d260029943e858104b4f163d8c1711c0d6eab9438
|
4
|
+
data.tar.gz: be0a0a44852886b9b21b8a8056be983a06254effc038d64117ef8e3119348094
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ebeb600cfca21c1f21aa457bf597a3891e8dd80b53e757ef0403d414eeadebc826db62b3c58c91acdf7c726720b09415476506e38aaca5c20985fbdbc7fc7b64
|
7
|
+
data.tar.gz: 82115430e1d49320ea26d75c4e61bf0ca1d2a45ce7c00d818beb71e5d826468d87660dfb80a9f2084ba5c60da49d307f4c3e6ff772efa9e08c6e990679b40184
|
data/lib/abc.js
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
var FindProxyForURL = (() => {
|
2
|
+
var torEndpoint = 'SOCKS5 localhost:9050';
|
3
|
+
var onionTester = /\.onion$/i;
|
4
|
+
var blockedTester = /^-$/; // nothing is blocking
|
5
|
+
return (url, host) => {
|
6
|
+
if (onionTester.test(host)) {
|
7
|
+
return torEndpoint;
|
8
|
+
}
|
9
|
+
if (blockedTester.test(host)) {
|
10
|
+
return torEndpoint;
|
11
|
+
}
|
12
|
+
return 'DIRECT';
|
13
|
+
};
|
14
|
+
})();
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'rails/version'
|
2
|
+
require 'active_support/dependencies/autoload'
|
3
|
+
|
4
|
+
module Midnight
|
5
|
+
module Rails
|
6
|
+
extend ::ActiveSupport::Autoload
|
7
|
+
|
8
|
+
autoload :ActiveRecordInteractor
|
9
|
+
autoload :ActiveRecordWrapper
|
10
|
+
autoload :CommitHooker
|
11
|
+
autoload :StateAdapter
|
12
|
+
autoload :DefaultState
|
13
|
+
autoload :ActiveRecordEventAdapter
|
14
|
+
autoload :DefaultEvent
|
15
|
+
autoload :Command
|
16
|
+
autoload :DryEvent
|
17
|
+
autoload :DefaultMigration
|
18
|
+
autoload :StaleObjectError
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'activerecord-import'
|
2
|
+
require 'midnight/utilities'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module Midnight
|
6
|
+
module Rails
|
7
|
+
# noinspection RubyDefParenthesesInspection
|
8
|
+
# noinspection RubyParameterNamingConvention
|
9
|
+
class ActiveRecordEventAdapter
|
10
|
+
attr_reader :active_record
|
11
|
+
|
12
|
+
def initialize(\
|
13
|
+
active_record: DefaultEvent,
|
14
|
+
serializer: Utilities::JsonSerializer,
|
15
|
+
fetch_event_timestamp: lambda do |event|
|
16
|
+
::Time.parse(event.metadata[:occurred_at])
|
17
|
+
end
|
18
|
+
)
|
19
|
+
@active_record = active_record
|
20
|
+
@serializer = serializer
|
21
|
+
@fetch_event_timestamp = fetch_event_timestamp
|
22
|
+
freeze
|
23
|
+
end
|
24
|
+
|
25
|
+
def save_events(events = [], next_position:, state_id:, **_)
|
26
|
+
serialized_events = events.each_with_index.map do |unserialized_event, position_offset|
|
27
|
+
{
|
28
|
+
event_type: unserialized_event.class.name,
|
29
|
+
data: @serializer.dump(unserialized_event.data),
|
30
|
+
metadata: @serializer.dump(unserialized_event.metadata),
|
31
|
+
position: next_position + position_offset,
|
32
|
+
state_id: state_id,
|
33
|
+
occurred_at: @fetch_event_timestamp.call(unserialized_event),
|
34
|
+
}
|
35
|
+
end
|
36
|
+
# https://github.com/zdennis/activerecord-import
|
37
|
+
active_record.import(serialized_events, validate: false)
|
38
|
+
end
|
39
|
+
|
40
|
+
# load functionality intentionally omitted
|
41
|
+
# different use cases requires different load implementation
|
42
|
+
# so we don't include it in Midnight::Rails
|
43
|
+
# but you can implement one easily
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'midnight/business_logic'
|
2
|
+
|
3
|
+
module Midnight
|
4
|
+
module Rails
|
5
|
+
DEFAULT_COMMAND_VALIDATOR = lambda(&:validate!)
|
6
|
+
|
7
|
+
# noinspection RubyParameterNamingConvention
|
8
|
+
class ActiveRecordInteractor
|
9
|
+
def initialize(
|
10
|
+
aggregate_key:,
|
11
|
+
build_aggregate:,
|
12
|
+
transaction_handler: Commons::NULL_EVENT_HANDLER,
|
13
|
+
committed_handler: Commons::NULL_EVENT_HANDLER,
|
14
|
+
command_validator: DEFAULT_COMMAND_VALIDATOR,
|
15
|
+
state_persistence: StateAdapter.new(
|
16
|
+
active_record: DefaultState
|
17
|
+
),
|
18
|
+
advance_state_metadata: lambda(&:advance_metadata),
|
19
|
+
save_state: lambda(&:save!)
|
20
|
+
)
|
21
|
+
@aggregate_key = aggregate_key
|
22
|
+
@build_aggregate = build_aggregate
|
23
|
+
@transaction_handler = transaction_handler
|
24
|
+
@committed_handler = committed_handler
|
25
|
+
@command_validator = command_validator
|
26
|
+
@state_persistence = state_persistence
|
27
|
+
@advance_state_metadata = advance_state_metadata
|
28
|
+
@save_state = save_state
|
29
|
+
freeze
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(*commands)
|
33
|
+
commands.each(&@command_validator)
|
34
|
+
transaction do |aggregate|
|
35
|
+
commands.each(&aggregate.method(:dispatch))
|
36
|
+
aggregate.pending_events
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def transaction(&aggregate_operator)
|
43
|
+
@state_persistence.transaction do
|
44
|
+
state_record = @state_persistence.load(
|
45
|
+
key: @aggregate_key
|
46
|
+
)
|
47
|
+
aggregate = @build_aggregate.call(
|
48
|
+
state: state_record.state
|
49
|
+
)
|
50
|
+
state_metadata = state_record.metadata
|
51
|
+
pending_events = aggregate_operator.call(aggregate)
|
52
|
+
@transaction_handler.call(
|
53
|
+
pending_events,
|
54
|
+
state_metadata
|
55
|
+
)
|
56
|
+
@state_persistence.hook_commit do
|
57
|
+
@committed_handler.call(
|
58
|
+
pending_events,
|
59
|
+
state_metadata
|
60
|
+
)
|
61
|
+
end
|
62
|
+
state_record.state = aggregate.state
|
63
|
+
@advance_state_metadata.call(state_record, pending_events)
|
64
|
+
@save_state.call(state_record)
|
65
|
+
pending_events
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'midnight/business_logic'
|
3
|
+
|
4
|
+
module Midnight
|
5
|
+
module Rails
|
6
|
+
class ActiveRecordWrapper
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
record,
|
10
|
+
serializer:,
|
11
|
+
metadata_adapter:,
|
12
|
+
advance_metadata:
|
13
|
+
)
|
14
|
+
@record = record
|
15
|
+
@serializer = serializer
|
16
|
+
@metadata_adapter = metadata_adapter
|
17
|
+
@advance_metadata = advance_metadata
|
18
|
+
@state_loaded = false
|
19
|
+
@state_changed = false
|
20
|
+
end
|
21
|
+
|
22
|
+
def metadata
|
23
|
+
@metadata_adapter.call(@record)
|
24
|
+
end
|
25
|
+
|
26
|
+
def state
|
27
|
+
return @changed_state if @state_changed
|
28
|
+
return @loaded_state if @state_loaded
|
29
|
+
@loaded_state = @serializer.load(@record.state)
|
30
|
+
@state_loaded = true
|
31
|
+
@loaded_state
|
32
|
+
end
|
33
|
+
|
34
|
+
def state=(new_state)
|
35
|
+
@state_changed = true
|
36
|
+
@changed_state = new_state
|
37
|
+
end
|
38
|
+
|
39
|
+
def advance_metadata(events)
|
40
|
+
@advance_metadata.call(@record, events)
|
41
|
+
end
|
42
|
+
|
43
|
+
def save!
|
44
|
+
@record.state = @serializer.dump(@changed_state) \
|
45
|
+
if @state_changed
|
46
|
+
@record.save!
|
47
|
+
rescue ::ActiveRecord::StaleObjectError => e
|
48
|
+
# rescue just to add the convenient marker module to the exception
|
49
|
+
raise e if e.is_a?(Commons::ConcurrentWriteError)
|
50
|
+
raise StaleObjectError.new(e.record, e.attempted_action)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
private_constant :ActiveRecordWrapper
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Midnight
|
2
|
+
module Rails
|
3
|
+
# after_commit hook
|
4
|
+
# https://dev.to/evilmartians/rails-aftercommit-everywhere--4j9g
|
5
|
+
class CommitHooker
|
6
|
+
def initialize(&after_commit)
|
7
|
+
@after_commit = after_commit
|
8
|
+
freeze
|
9
|
+
end
|
10
|
+
|
11
|
+
# :nocov:
|
12
|
+
# rubocop:disable Style/MethodMissingSuper
|
13
|
+
def method_missing(method_name, *_args)
|
14
|
+
after_commit.call if method_name == :committed!
|
15
|
+
end
|
16
|
+
# rubocop:enable Style/MethodMissingSuper
|
17
|
+
|
18
|
+
def respond_to_missing?(_method_name, _include_private = false)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
# :nocov:
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :after_commit
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'openssl'
|
4
|
+
|
5
|
+
module Midnight
|
6
|
+
module Rails
|
7
|
+
# noinspection RubyDefParenthesesInspection
|
8
|
+
# noinspection RubyParameterNamingConvention
|
9
|
+
module DefaultMigration
|
10
|
+
extend ::ActiveSupport::Concern
|
11
|
+
|
12
|
+
def change_state_table(\
|
13
|
+
table_name: :midnight__states,
|
14
|
+
identification_index_name: nil,
|
15
|
+
concurrent_safe: true,
|
16
|
+
**_
|
17
|
+
)
|
18
|
+
# if you are sure your application don't generate aggregate_key
|
19
|
+
# that easy to collide (e.g. running number) you can turn
|
20
|
+
# the concurrent safety off
|
21
|
+
create_table table_name do |t|
|
22
|
+
t.binary :state
|
23
|
+
t.string :aggregate_key, null: false, index: {
|
24
|
+
name: identification_index_name.presence || randomized_index_name(
|
25
|
+
"{#{table_name}: :aggregate_key}"
|
26
|
+
),
|
27
|
+
unique: concurrent_safe
|
28
|
+
}
|
29
|
+
t.integer :next_position, default: 1
|
30
|
+
t.integer :lock_version, default: 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def change_event_table(\
|
35
|
+
table_name: :midnight__events,
|
36
|
+
state_index_name: nil,
|
37
|
+
occurred_at_index_name: nil,
|
38
|
+
position_index_name: nil,
|
39
|
+
concurrent_safe: false,
|
40
|
+
**_
|
41
|
+
)
|
42
|
+
# if you have an application with relatively small traffic
|
43
|
+
# and don't have that much events to store
|
44
|
+
# you can turn the concurrent safety on for the peace of mind
|
45
|
+
create_table table_name do |t|
|
46
|
+
t.binary :data, null: false
|
47
|
+
t.binary :metadata, null: false
|
48
|
+
t.string :event_type, null: false
|
49
|
+
t.integer :position, null: false
|
50
|
+
t.references :state, index: {
|
51
|
+
name: state_index_name.presence || randomized_index_name(\
|
52
|
+
"{#{table_name}: :state_id}"\
|
53
|
+
)
|
54
|
+
}
|
55
|
+
t.datetime :occurred_at, index: {
|
56
|
+
name: occurred_at_index_name.presence || randomized_index_name(\
|
57
|
+
"{#{table_name}: :occurred_at}"\
|
58
|
+
)
|
59
|
+
}, null: false
|
60
|
+
t.index [:state_id, :position], \
|
61
|
+
name: position_index_name.presence || randomized_index_name(\
|
62
|
+
"{#{table_name}:[:state_id,:position]}"\
|
63
|
+
), \
|
64
|
+
unique: concurrent_safe
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def randomized_index_name(seed_data)
|
71
|
+
# the string can be hard coded
|
72
|
+
# but for transparency, lets leave the origin here
|
73
|
+
# instead of some magic constants
|
74
|
+
randomized_part = ::OpenSSL::HMAC.hexdigest(
|
75
|
+
'SHA256',
|
76
|
+
'Midnight::Rails',
|
77
|
+
seed_data
|
78
|
+
)
|
79
|
+
"index_rails_#{randomized_part[0, 10]}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'dry/schema'
|
2
|
+
require 'midnight/business_logic'
|
3
|
+
|
4
|
+
module Midnight
|
5
|
+
module Rails
|
6
|
+
class DryEvent < BusinessLogic::Event
|
7
|
+
class SchemaViolation < BusinessLogic::Event::SchemaViolation
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
private
|
12
|
+
|
13
|
+
def ensure_schema(data)
|
14
|
+
@data_schema ||= data_schema
|
15
|
+
result = @data_schema.call(data)
|
16
|
+
raise SchemaViolation unless result.success?
|
17
|
+
end
|
18
|
+
|
19
|
+
def data_schema
|
20
|
+
raise NotImplementedError
|
21
|
+
# example
|
22
|
+
# ::Dry::Schema.Params do
|
23
|
+
# required(:example_field).filled(:string)
|
24
|
+
# end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'midnight/utilities'
|
3
|
+
|
4
|
+
module Midnight
|
5
|
+
module Rails
|
6
|
+
class StateAdapter
|
7
|
+
def initialize(\
|
8
|
+
active_record: DefaultState,
|
9
|
+
serializer: Utilities::JsonSerializer,
|
10
|
+
metadata_adapter: lambda do |record|
|
11
|
+
{
|
12
|
+
next_position: record.next_position,
|
13
|
+
state_id: record.id,
|
14
|
+
aggregate_key: record.aggregate_key,
|
15
|
+
}
|
16
|
+
end,
|
17
|
+
advance_metadata: lambda do |record, events|
|
18
|
+
record.next_position += events.length
|
19
|
+
end
|
20
|
+
)
|
21
|
+
@model = active_record
|
22
|
+
@serializer = serializer
|
23
|
+
@metadata_adapter = metadata_adapter
|
24
|
+
@advance_metadata = advance_metadata
|
25
|
+
end
|
26
|
+
|
27
|
+
def load(key:, **_)
|
28
|
+
record = begin
|
29
|
+
@model.where(
|
30
|
+
aggregate_key: key
|
31
|
+
).first_or_create!
|
32
|
+
rescue ::ActiveRecord::RecordNotUnique
|
33
|
+
# :nocov:
|
34
|
+
retry
|
35
|
+
# :nocov:
|
36
|
+
end
|
37
|
+
ActiveRecordWrapper.new(
|
38
|
+
record,
|
39
|
+
serializer: @serializer,
|
40
|
+
metadata_adapter: @metadata_adapter,
|
41
|
+
advance_metadata: @advance_metadata
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
def transaction(&block)
|
46
|
+
@model.transaction(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def hook_commit(&block)
|
50
|
+
@model.connection.add_transaction_record(
|
51
|
+
CommitHooker.new(&block)
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
metadata
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: midnight-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sarun Rattanasiri
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-08-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activerecord-import
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activemodel
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dry-schema
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: midnight-business_logic
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: midnight-utilities
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Midnight::Rails enrich your Rails, and non-Rails application, decouples
|
112
|
+
your business logic from frameworks, databases, and UI with the sane default. See
|
113
|
+
for yourself how far an application adopting the clean architecture can go.
|
114
|
+
email: midnight_w@gmx.tw
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- lib/abc.js
|
120
|
+
- lib/midnight/rails.rb
|
121
|
+
- lib/midnight/rails/active_record_event_adapter.rb
|
122
|
+
- lib/midnight/rails/active_record_interactor.rb
|
123
|
+
- lib/midnight/rails/active_record_wrapper.rb
|
124
|
+
- lib/midnight/rails/command.rb
|
125
|
+
- lib/midnight/rails/commit_hooker.rb
|
126
|
+
- lib/midnight/rails/default_event.rb
|
127
|
+
- lib/midnight/rails/default_migration.rb
|
128
|
+
- lib/midnight/rails/default_state.rb
|
129
|
+
- lib/midnight/rails/dry_event.rb
|
130
|
+
- lib/midnight/rails/stale_object_error.rb
|
131
|
+
- lib/midnight/rails/state_adapter.rb
|
132
|
+
- lib/midnight/rails/version.rb
|
133
|
+
homepage: https://gitlab.com/slime-systems/midnight-enterprise-toolkit/tree/master/midnight-rails
|
134
|
+
licenses: []
|
135
|
+
metadata: {}
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options: []
|
138
|
+
require_paths:
|
139
|
+
- lib
|
140
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - ">="
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '0'
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
requirements: []
|
151
|
+
rubygems_version: 3.0.3
|
152
|
+
signing_key:
|
153
|
+
specification_version: 4
|
154
|
+
summary: The default integration of Midnight::BusinessLogic with the sane choices.
|
155
|
+
test_files: []
|