activefunction-core 0.0.1 → 0.1.1
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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/.rbnext/3.0/plugins/hooks.rb +138 -0
- data/lib/active_function_core/version.rb +1 -1
- data/lib/active_function_core.rb +2 -0
- data/lib/plugins/hooks.rb +138 -0
- metadata +6 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7598948c858b823027e2c33a190a17920f466ce55ea96138bc9a01ac75899e74
|
4
|
+
data.tar.gz: 57b9189b07f384420404db190dcea2cd2b7aa40e714f732713f252fddb34590d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10c87d5b48dcbb1fc3e0aa0711d4dcc4125f6210bbd0b1f96d081e4aadb6bf0feb6028abc0161fa69ca3fd380b5001ec044bc833cc83f5da9479772da16ad133
|
7
|
+
data.tar.gz: 124281e35afce65ca63ca07a4e80ac32167b97104f2c22ab70578fdf280989ef75fc1131dbeef003991857f1462dd0f9eb87b5c00197080573c1cd71ed3a7f09
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveFunctionCore
|
4
|
+
module Plugins
|
5
|
+
module Hooks
|
6
|
+
class MissingCallbackContext < Error
|
7
|
+
MESSAGE_TEMPLATE = "Missing callback context: %s"
|
8
|
+
|
9
|
+
attr_reader :message
|
10
|
+
|
11
|
+
def initialize(context)
|
12
|
+
@message = MESSAGE_TEMPLATE % context
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MissingHookableMethod < Error
|
17
|
+
MESSAGE_TEMPLATE = "Method %s is not defined"
|
18
|
+
|
19
|
+
attr_reader :message
|
20
|
+
|
21
|
+
def initialize(method_name)
|
22
|
+
@message = MESSAGE_TEMPLATE % method_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.included(base)
|
27
|
+
base.extend(ClassMethods)
|
28
|
+
base.include(InstanceMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
module InstanceMethods
|
32
|
+
private
|
33
|
+
|
34
|
+
def with_callbacks(method_name, &block)
|
35
|
+
callbacks = _callbacks(method_name)
|
36
|
+
|
37
|
+
_run_callbacks(callbacks.before)
|
38
|
+
|
39
|
+
result = yield
|
40
|
+
|
41
|
+
_run_callbacks(callbacks.after)
|
42
|
+
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
def _callbacks(method_name)
|
47
|
+
self.class.hooks[method_name].callbacks
|
48
|
+
end
|
49
|
+
|
50
|
+
def _run_callbacks(callbacks)
|
51
|
+
callbacks.each do |callback|
|
52
|
+
raise(MissingCallbackContext, callback) unless respond_to?(callback.target, true)
|
53
|
+
|
54
|
+
send(callback.target) if _executable?(callback.options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def _executable?(options)
|
59
|
+
return false if options[:if] && !send(options[:if])
|
60
|
+
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module ClassMethods
|
66
|
+
TYPES = %i[before after].freeze
|
67
|
+
# rubocop:disable Lint/ConstantDefinitionInBlock
|
68
|
+
Hooks = Data.define(:hooks) do
|
69
|
+
def initialize(hooks: {}) ; super; end
|
70
|
+
def deep_dup ; Marshal.load(Marshal.dump(self)); end
|
71
|
+
def all ; hooks; end
|
72
|
+
def [](method_name) ; hooks[method_name]; end
|
73
|
+
|
74
|
+
def add_hook(method_name)
|
75
|
+
hooks[method_name] = Hook[method_name]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Hook = Data.define(:method_name, :callbacks) do
|
80
|
+
Callbacks = Data.define(:before, :after) do
|
81
|
+
def initialize(before: [], after: []) ; super; end
|
82
|
+
def [](type) ; public_send(type); end
|
83
|
+
end
|
84
|
+
Callback = Data.define(:target, :options)
|
85
|
+
|
86
|
+
def initialize(method_name:, callbacks: Callbacks.new) ; super; end
|
87
|
+
def hashes(type) ; Set.new callbacks[type].map(&:hash); end
|
88
|
+
|
89
|
+
def add_callback(type:, target:, options: {})
|
90
|
+
new_callbacks = Callback[target, options]
|
91
|
+
callbacks[type] << new_callbacks unless hashes(type) === new_callbacks.hash
|
92
|
+
end
|
93
|
+
end
|
94
|
+
# rubocop:enable Lint/ConstantDefinitionInBlock
|
95
|
+
|
96
|
+
def define_hooks_for(*method_names)
|
97
|
+
method_names.each do |method_name|
|
98
|
+
override_hookable_method(method_name)
|
99
|
+
|
100
|
+
hooks.add_hook(method_name)
|
101
|
+
|
102
|
+
define_callback_methods_for(method_name)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_callback(type, method_name, target, options = {})
|
107
|
+
hooks[method_name].add_callback(type: type, target: target, options: options)
|
108
|
+
end
|
109
|
+
|
110
|
+
def hooks
|
111
|
+
@__hooks ||= Hooks.new
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def inherited(subclass)
|
117
|
+
subclass.instance_variable_set(:@__hooks, @__hooks.deep_dup)
|
118
|
+
end
|
119
|
+
|
120
|
+
def override_hookable_method(method_name)
|
121
|
+
raise(MissingHookableMethod, method_name) unless method_defined?(method_name)
|
122
|
+
|
123
|
+
define_method(method_name) do |*args|
|
124
|
+
with_callbacks(method_name) { super(*args) }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def define_callback_methods_for(method_name)
|
129
|
+
TYPES.each do |type|
|
130
|
+
define_singleton_method("#{type}_#{method_name}") do |target, options = {}|
|
131
|
+
set_callback(type, method_name, target, options)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
data/lib/active_function_core.rb
CHANGED
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveFunctionCore
|
4
|
+
module Plugins
|
5
|
+
module Hooks
|
6
|
+
class MissingCallbackContext < Error
|
7
|
+
MESSAGE_TEMPLATE = "Missing callback context: %s"
|
8
|
+
|
9
|
+
attr_reader :message
|
10
|
+
|
11
|
+
def initialize(context)
|
12
|
+
@message = MESSAGE_TEMPLATE % context
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class MissingHookableMethod < Error
|
17
|
+
MESSAGE_TEMPLATE = "Method %s is not defined"
|
18
|
+
|
19
|
+
attr_reader :message
|
20
|
+
|
21
|
+
def initialize(method_name)
|
22
|
+
@message = MESSAGE_TEMPLATE % method_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.included(base)
|
27
|
+
base.extend(ClassMethods)
|
28
|
+
base.include(InstanceMethods)
|
29
|
+
end
|
30
|
+
|
31
|
+
module InstanceMethods
|
32
|
+
private
|
33
|
+
|
34
|
+
def with_callbacks(method_name, &block)
|
35
|
+
callbacks = _callbacks(method_name)
|
36
|
+
|
37
|
+
_run_callbacks(callbacks.before)
|
38
|
+
|
39
|
+
result = yield
|
40
|
+
|
41
|
+
_run_callbacks(callbacks.after)
|
42
|
+
|
43
|
+
result
|
44
|
+
end
|
45
|
+
|
46
|
+
def _callbacks(method_name)
|
47
|
+
self.class.hooks[method_name].callbacks
|
48
|
+
end
|
49
|
+
|
50
|
+
def _run_callbacks(callbacks)
|
51
|
+
callbacks.each do |callback|
|
52
|
+
raise(MissingCallbackContext, callback) unless respond_to?(callback.target, true)
|
53
|
+
|
54
|
+
send(callback.target) if _executable?(callback.options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def _executable?(options)
|
59
|
+
return false if options[:if] && !send(options[:if])
|
60
|
+
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module ClassMethods
|
66
|
+
TYPES = %i[before after].freeze
|
67
|
+
# rubocop:disable Lint/ConstantDefinitionInBlock
|
68
|
+
Hooks = Data.define(:hooks) do
|
69
|
+
def initialize(hooks: {}) = super
|
70
|
+
def deep_dup = Marshal.load(Marshal.dump(self))
|
71
|
+
def all = hooks
|
72
|
+
def [](method_name) = hooks[method_name]
|
73
|
+
|
74
|
+
def add_hook(method_name)
|
75
|
+
hooks[method_name] = Hook[method_name]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Hook = Data.define(:method_name, :callbacks) do
|
80
|
+
Callbacks = Data.define(:before, :after) do
|
81
|
+
def initialize(before: [], after: []) = super
|
82
|
+
def [](type) = public_send(type)
|
83
|
+
end
|
84
|
+
Callback = Data.define(:target, :options)
|
85
|
+
|
86
|
+
def initialize(method_name:, callbacks: Callbacks.new) = super
|
87
|
+
def hashes(type) = Set.new callbacks[type].map(&:hash)
|
88
|
+
|
89
|
+
def add_callback(type:, target:, options: {})
|
90
|
+
new_callbacks = Callback[target, options]
|
91
|
+
callbacks[type] << new_callbacks unless hashes(type) === new_callbacks.hash
|
92
|
+
end
|
93
|
+
end
|
94
|
+
# rubocop:enable Lint/ConstantDefinitionInBlock
|
95
|
+
|
96
|
+
def define_hooks_for(*method_names)
|
97
|
+
method_names.each do |method_name|
|
98
|
+
override_hookable_method(method_name)
|
99
|
+
|
100
|
+
hooks.add_hook(method_name)
|
101
|
+
|
102
|
+
define_callback_methods_for(method_name)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_callback(type, method_name, target, options = {})
|
107
|
+
hooks[method_name].add_callback(type: type, target: target, options: options)
|
108
|
+
end
|
109
|
+
|
110
|
+
def hooks
|
111
|
+
@__hooks ||= Hooks.new
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def inherited(subclass)
|
117
|
+
subclass.instance_variable_set(:@__hooks, @__hooks.deep_dup)
|
118
|
+
end
|
119
|
+
|
120
|
+
def override_hookable_method(method_name)
|
121
|
+
raise(MissingHookableMethod, method_name) unless method_defined?(method_name)
|
122
|
+
|
123
|
+
define_method(method_name) do |*args|
|
124
|
+
with_callbacks(method_name) { super(*args) }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def define_callback_methods_for(method_name)
|
129
|
+
TYPES.each do |type|
|
130
|
+
define_singleton_method("#{type}_#{method_name}") do |target, options = {}|
|
131
|
+
set_callback(type, method_name, target, options)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activefunction-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nerbyk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-next-core
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0.15'
|
20
17
|
- - ">="
|
21
18
|
- !ruby/object:Gem::Version
|
22
|
-
version: 0.
|
19
|
+
version: 1.0.0
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- - "~>"
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
version: '0.15'
|
30
24
|
- - ">="
|
31
25
|
- !ruby/object:Gem::Version
|
32
|
-
version: 0.
|
26
|
+
version: 1.0.0
|
33
27
|
description: Provides core functionality, plugins and ruby-next integration for ActiveFunction
|
34
28
|
email:
|
35
29
|
- danil.maximov2000@gmail.com
|
@@ -40,8 +34,10 @@ files:
|
|
40
34
|
- CHANGELOG.md
|
41
35
|
- LICENSE.txt
|
42
36
|
- README.md
|
37
|
+
- lib/.rbnext/3.0/plugins/hooks.rb
|
43
38
|
- lib/active_function_core.rb
|
44
39
|
- lib/active_function_core/version.rb
|
40
|
+
- lib/plugins/hooks.rb
|
45
41
|
- sig/active_function_core.rbs
|
46
42
|
- sig/manifest.yml
|
47
43
|
homepage: https://github.com/DanilMaximov/activefunction
|