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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91ff45a5d0f2788d853ccb9a8b89167e73362f04bdf0a840e3011897031b7003
4
- data.tar.gz: 5b36aa6e6969448af121132648ad2204365f98aa465d83e84b65726219a88b43
3
+ metadata.gz: 1e1231c5c1338d3a4f5c7db47db5ab36cdd4d032f4eb97ad10e50798397e4580
4
+ data.tar.gz: 9c1afa1729571899206394d775f96ba25366f5c9565b43d55fe80c9c3f7f8edf
5
5
  SHA512:
6
- metadata.gz: 3685049da7f4de449edcd7f71f9de4b75d56b46b9d39180791b0337f875542a52029f305dd72dabdfb75566cfc703d04ebc98e82e21483c0cd07c1388aee032f
7
- data.tar.gz: c0313bc7fcf70e68d49172dc912fd6e57e5bc2fb611e85eb5877d21cc3c35185c263b7c2ada611b4f2aca931a66aec056d43c1dabb518d8fbe79464b12de19d8
6
+ metadata.gz: 9fcb1943a5af08b284ab7fc16c74d78949a466f2e1a8dca4f910ca8d8c2e883848137e9fbe2d6cf04ee55148b36efced176770f68dc9a0ef120f63b11c95fe26
7
+ data.tar.gz: 1d09ecd42b89e86c0c7362987ee23809100e9c70e9d83fd7cac1e4bea4963493db50bb50573ab118ae150f843cebe55fd6b3d64eb4a1c73ee0fdd4b6a360d2af
@@ -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
- method_name = method_name.to_sym
27
- original_method = klass.instance_method(method_name)
28
- method_observe = observer_method(method_name)
29
- method_dump = method_dump(method_name)
30
- me = self
31
-
32
- return false if method_defined?(klass, method_dump)
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.send(:define_method, method_observe, observer_method_proc)
36
+ observe_method!(klass, method_names, skip_if: skip_if, instance_method: instance_method, &main_block)
37
+ end
50
38
 
51
- klass.send(:alias_method, method_name, method_observe) # redefine the original method
52
- add_observed(klass, method_name)
53
- true
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
- method_observe = observer_method(method_name)
65
- method_dump = method_dump(method_name)
66
- return false unless method_defined?(klass, method_observe) && method_defined?(klass, method_dump)
67
-
68
- klass.send(:alias_method, method_name, method_dump) # restore dumped method
69
- klass.send(:remove_method, method_observe) # remove observed method
70
- klass.send(:remove_method, method_dump) # remove dump method
71
- remove_from_observed(klass, method_name)
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 observer_method(method)
106
- "#{method}_observer"
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 method_dump(method)
110
- "#{method}_dump"
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 add_observed(klass, method_name)
122
- observed_methods << klass_with_method(klass, method_name)
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 remove_from_observed(klass, method_name)
126
- observed_methods.delete(klass_with_method(klass, method_name))
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; end
211
+ class ExecuteBlockWasNotDefined < StandardError;
212
+ end
130
213
  end
131
214
  end
@@ -1,3 +1,3 @@
1
1
  module Methodist
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
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.2
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: 2018-11-26 00:00:00.000000000 Z
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
- rubyforge_project:
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.