methodist 0.1.2 → 0.1.3
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/lib/methodist/observer.rb +132 -49
- data/lib/methodist/version.rb +1 -1
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1e1231c5c1338d3a4f5c7db47db5ab36cdd4d032f4eb97ad10e50798397e4580
|
4
|
+
data.tar.gz: 9c1afa1729571899206394d775f96ba25366f5c9565b43d55fe80c9c3f7f8edf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fcb1943a5af08b284ab7fc16c74d78949a466f2e1a8dca4f910ca8d8c2e883848137e9fbe2d6cf04ee55148b36efced176770f68dc9a0ef120f63b11c95fe26
|
7
|
+
data.tar.gz: 1d09ecd42b89e86c0c7362987ee23809100e9c70e9d83fd7cac1e4bea4963493db50bb50573ab118ae150f843cebe55fd6b3d64eb4a1c73ee0fdd4b6a360d2af
|
data/lib/methodist/observer.rb
CHANGED
@@ -15,42 +15,44 @@ class Methodist::Observer < Methodist::Pattern
|
|
15
15
|
# * +method_name+ [String/Symbol] - Observation method name
|
16
16
|
#
|
17
17
|
# ===== Options
|
18
|
-
# * +skip_if+ [Proc] - Skip triggered execution if condition is true
|
18
|
+
# * +skip_if+ [Proc] - Skip triggered execution if condition is true (default nil)
|
19
|
+
# * +instance_method+ [Boolean] - True if observer klass instance method, false if observer klass method (default true)
|
19
20
|
#
|
20
21
|
# ==== Yield
|
21
22
|
# main_block - execution block. If this block was passed,
|
22
23
|
# `#execute` block will be ignored
|
23
24
|
#
|
24
25
|
##
|
25
|
-
def observe(klass, method_name, skip_if: nil, &main_block)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
klass.send(:alias_method, method_dump, method_name) # dump method
|
35
|
-
|
36
|
-
observer_method_proc = -> (*args, &block) do
|
37
|
-
result = original_method.bind(self).call(*args, &block)
|
38
|
-
unless skip_if.nil?
|
39
|
-
return if skip_if.call(result)
|
40
|
-
end
|
41
|
-
if block_given?
|
42
|
-
main_block.call(klass, method_name)
|
43
|
-
else
|
44
|
-
me.trigger!(klass, method_name)
|
45
|
-
end
|
46
|
-
result # return the result of the original method
|
26
|
+
def observe(klass, method_name, skip_if: nil, instance_method: true, &main_block)
|
27
|
+
method_names = generate_method_names(method_name)
|
28
|
+
|
29
|
+
# Make dump original method.
|
30
|
+
if instance_method
|
31
|
+
alias_instance_method(klass, method_names[:dump], method_names[:name])
|
32
|
+
else
|
33
|
+
alias_class_method(klass, method_names[:dump], method_names[:name])
|
47
34
|
end
|
48
35
|
|
49
|
-
klass
|
36
|
+
observe_method!(klass, method_names, skip_if: skip_if, instance_method: instance_method, &main_block)
|
37
|
+
end
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
39
|
+
##
|
40
|
+
# Subscribe to the class method of the klass to observe
|
41
|
+
#
|
42
|
+
# ==== Parameters
|
43
|
+
# * +klass+ [Class] - The owner of the method for observation
|
44
|
+
# * +method_name+ [String/Symbol] - Observation method name
|
45
|
+
#
|
46
|
+
# ===== Options
|
47
|
+
# * +skip_if+ [Proc] - Skip triggered execution if condition is true
|
48
|
+
#
|
49
|
+
# ==== Yield
|
50
|
+
# main_block - execution block. If this block was passed,
|
51
|
+
# `#execute` block will be ignored
|
52
|
+
#
|
53
|
+
##
|
54
|
+
def observe_class_method(klass, method_name, skip_if: nil, &main_block)
|
55
|
+
observe(klass, method_name, skip_if: skip_if, instance_method: false, &main_block)
|
54
56
|
end
|
55
57
|
|
56
58
|
##
|
@@ -60,15 +62,28 @@ class Methodist::Observer < Methodist::Pattern
|
|
60
62
|
# * +klass+ [Class] - Klass owner of the observed method
|
61
63
|
# * +method_name+ [String/Symbol] - Name of the observed method
|
62
64
|
##
|
63
|
-
def stop_observe(klass, method_name)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
65
|
+
def stop_observe(klass, method_name, instance_method: true)
|
66
|
+
method_names = generate_method_names(method_name)
|
67
|
+
|
68
|
+
if instance_method
|
69
|
+
unless method_defined?(klass, method_names[:observed]) && method_defined?(klass, method_names[:dump])
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
klass.send(:alias_method, method_names[:name], method_names[:dump]) # restore dumped instance method
|
74
|
+
klass.send(:remove_method, method_names[:observed]) # remove observed instance method
|
75
|
+
klass.send(:remove_method, method_names[:dump]) # remove dump instance method
|
76
|
+
else
|
77
|
+
unless klass_method_defined?(klass, method_names[:observed]) && klass_method_defined?(klass, method_names[:dump])
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
|
81
|
+
klass.singleton_class.send(:alias_method, method_names[:name], method_names[:dump]) # restore dumped class method
|
82
|
+
klass.singleton_class.send(:remove_method, method_names[:observed]) # remove observed class method
|
83
|
+
klass.singleton_class.send(:remove_method, method_names[:dump]) # remove dump class method
|
84
|
+
end
|
85
|
+
|
86
|
+
remove_from_observed(klass, method_names[:name], instance_method: instance_method)
|
72
87
|
true
|
73
88
|
end
|
74
89
|
|
@@ -83,10 +98,10 @@ class Methodist::Observer < Methodist::Pattern
|
|
83
98
|
# ===== Raise
|
84
99
|
# +ExecuteBlockWasNotDefined+ - when no block was passed to the execute method in the observer class
|
85
100
|
##
|
86
|
-
def trigger!(klass, method_name)
|
101
|
+
def trigger!(klass, method_name, result, *args)
|
87
102
|
block = const_get(CONST_EXECUTION_BLOCK) rescue nil
|
88
103
|
raise ExecuteBlockWasNotDefined, "You must define execute block in your #{self.name}" unless block
|
89
|
-
block.call(klass, method_name)
|
104
|
+
block.call(klass, method_name, result, *args)
|
90
105
|
end
|
91
106
|
|
92
107
|
##
|
@@ -102,30 +117,98 @@ class Methodist::Observer < Methodist::Pattern
|
|
102
117
|
|
103
118
|
private
|
104
119
|
|
105
|
-
def
|
106
|
-
|
120
|
+
def observe_method!(klass, method_names, skip_if:, instance_method: true, &main_block)
|
121
|
+
observed_method_proc = observer_proc(
|
122
|
+
klass,
|
123
|
+
method_names[:name],
|
124
|
+
skip_if,
|
125
|
+
instance_method: instance_method,
|
126
|
+
&main_block
|
127
|
+
)
|
128
|
+
|
129
|
+
if instance_method
|
130
|
+
define_instance_method(klass, method_names[:observed], observed_method_proc)
|
131
|
+
alias_instance_method(klass, method_names[:name], method_names[:observed]) # redefine the original method
|
132
|
+
else
|
133
|
+
define_class_method(klass, method_names[:observed], observed_method_proc)
|
134
|
+
alias_class_method(klass, method_names[:name], method_names[:observed])
|
135
|
+
end
|
136
|
+
add_observed(klass, method_names[:name], instance_method: instance_method)
|
137
|
+
|
138
|
+
true
|
107
139
|
end
|
108
140
|
|
109
|
-
def
|
110
|
-
|
141
|
+
def observer_proc(klass, method_name, skip_if, instance_method: true, &main_block)
|
142
|
+
original_method = instance_method ? klass.instance_method(method_name) : klass.method(method_name)
|
143
|
+
me = self
|
144
|
+
|
145
|
+
-> (*args, &block) do
|
146
|
+
result = if instance_method
|
147
|
+
# We must inject context to instance method before call
|
148
|
+
original_method.bind(self).call(*args, &block)
|
149
|
+
else
|
150
|
+
original_method.call(*args, &block)
|
151
|
+
end
|
152
|
+
|
153
|
+
unless skip_if.nil?
|
154
|
+
return if skip_if.call(result)
|
155
|
+
end
|
156
|
+
|
157
|
+
if block_given?
|
158
|
+
main_block.call(klass, method_name, result, *args)
|
159
|
+
else
|
160
|
+
me.trigger!(klass, method_name, result, *args)
|
161
|
+
end
|
162
|
+
|
163
|
+
result # return the result of the original method
|
164
|
+
end
|
111
165
|
end
|
112
166
|
|
113
|
-
def klass_with_method(klass, method)
|
114
|
-
"#{klass}##{method}"
|
167
|
+
def klass_with_method(klass, method, instance_method: true)
|
168
|
+
instance_method ? "#{klass}##{method}" : "<ClassMethod:#{klass}##{method}"
|
115
169
|
end
|
116
170
|
|
117
171
|
def method_defined?(klass, method)
|
118
172
|
klass.instance_methods(false).include?(method.to_sym)
|
119
173
|
end
|
120
174
|
|
121
|
-
def
|
122
|
-
|
175
|
+
def klass_method_defined?(klass, method)
|
176
|
+
klass.methods(false).include?(method.to_sym)
|
177
|
+
end
|
178
|
+
|
179
|
+
def alias_instance_method(klass, alias_method, original_method)
|
180
|
+
klass.send(:alias_method, alias_method, original_method)
|
181
|
+
end
|
182
|
+
|
183
|
+
def alias_class_method(klass, alias_method, original_method)
|
184
|
+
klass.singleton_class.send(:alias_method, alias_method, original_method)
|
185
|
+
end
|
186
|
+
|
187
|
+
def define_instance_method(klass, method_name, proc)
|
188
|
+
klass.send(:define_method, method_name, proc)
|
189
|
+
end
|
190
|
+
|
191
|
+
def define_class_method(klass, method_name, proc)
|
192
|
+
klass.singleton_class.send(:define_method, method_name, proc)
|
193
|
+
end
|
194
|
+
|
195
|
+
def add_observed(klass, method_name, instance_method: true)
|
196
|
+
observed_methods << klass_with_method(klass, method_name, instance_method: instance_method)
|
197
|
+
end
|
198
|
+
|
199
|
+
def remove_from_observed(klass, method_name, instance_method: true)
|
200
|
+
observed_methods.delete(klass_with_method(klass, method_name, instance_method: instance_method))
|
123
201
|
end
|
124
202
|
|
125
|
-
def
|
126
|
-
|
203
|
+
def generate_method_names(method_name)
|
204
|
+
{
|
205
|
+
name: method_name.to_sym,
|
206
|
+
observed: "_methodist_#{method_name}_observer",
|
207
|
+
dump: "_methodist_#{method_name}_dump",
|
208
|
+
}
|
127
209
|
end
|
128
210
|
|
129
|
-
class ExecuteBlockWasNotDefined < StandardError;
|
211
|
+
class ExecuteBlockWasNotDefined < StandardError;
|
212
|
+
end
|
130
213
|
end
|
131
214
|
end
|
data/lib/methodist/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: methodist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Nesterov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -165,8 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
167
|
requirements: []
|
168
|
-
|
169
|
-
rubygems_version: 2.7.6
|
168
|
+
rubygems_version: 3.0.1
|
170
169
|
signing_key:
|
171
170
|
specification_version: 4
|
172
171
|
summary: Gem for Ruby on Rails created to stop chaos in your buisness logic.
|