methodist 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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.