stub_a 0.0.1 → 0.0.2

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/stub_a.rb +231 -56
  3. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 022265f955db24a8dd7a3bb3465243121379ecd8
4
- data.tar.gz: 86be306baf3ec972fdf4163e7ced3920e7bc4407
3
+ metadata.gz: c5c160196910a2a2749394b33cf6f8bab32c513b
4
+ data.tar.gz: 761a09839f11949d5bcafe88cea8828537e7dbf2
5
5
  SHA512:
6
- metadata.gz: aaff64bee34e4ce474b09fe009188c83af14b39128cd44bbaddc55d8055e4e71a7aeb789d097ae45acc8d685f0890571e8603da53178a7223c4a19a0a1a5c639
7
- data.tar.gz: d156071d484adaf0b2be902a1eb7903c33c9b9d2fd0271371e4b472aca42387d2a3b5120703c3256da55ba17357fbd64b0c80ea0bc402a77f5af9023fcadc4ea
6
+ metadata.gz: 8c1f8f4a27b708b5e80a087e3c911c6380aadfd275453fd24cfc7550a7edadee9625d9a8f09158a1a974448073d689de715db7c54796882ad0feb757f14c1711
7
+ data.tar.gz: cf1754d3a5414126cacdac2485279405bfcbab2fa8377dbfcaa0be446bcc2a36d3f4dbd6fdf420ce4562676341f65507e7f8b3bb364d6f475429d316b5bd86ae
@@ -1,35 +1,220 @@
1
+ # coding: utf-8
2
+
1
3
  class StubA
4
+ # コンストラクタ
5
+ #
6
+ # ==詳細
7
+ # 操作対象のクラスまたはインスタンスを渡し、
8
+ # 操作用オブジェクトを作成します。
9
+ #
10
+ # インスタンスが渡された場合、インスタンス
11
+ # メソッドに対するフックは特異メソッドとして
12
+ # 作成されます。
13
+ #
14
+ # クラスメソッドは、もともと特異メソッドの
15
+ # ようなものなので、クラスメソッドに対する操作は
16
+ # インスタンスを渡してもクラスを渡しても
17
+ # 変わりません。
18
+ #
19
+ # ==引数
20
+ # - ++object+: クラスまたはインスタンス
2
21
  def initialize(object)
3
- @target_class = object if object.is_a? Class
4
- @target_class ||= class << object; self; end
22
+ if object.is_a? Class
23
+ @target = object
24
+ @target_class = class << object; self; end
25
+ else
26
+ @target = class << object; self; end
27
+ @target_class = class << object.class; self; end
28
+ end
29
+ end
30
+
31
+ # インスタンスメソッドに対する before フックを作成
32
+ #
33
+ # ==詳細
34
+ # 引数で指定したインスタンスメソッドが実行される
35
+ # 直前に呼ばれるフックメソッドを作成します。
36
+ #
37
+ # 対象のメソッドはメソッド名で指定します。
38
+ #
39
+ # ==引数
40
+ # - ++method_name++: メソッド名
41
+ #
42
+ def before(method_name, &block)
43
+ make_hook(:before, @target, method_name, &block)
5
44
  end
6
45
 
7
- [:before,
8
- :after,
9
- ].each do |hook_type|
10
- define_method hook_type, ->(method, &block) {
11
- make_hook_points(method)
46
+ # クラスメソッドに対する before フックを作成
47
+ #
48
+ # ==詳細
49
+ # 引数で指定したクラスメソッドが実行される直前に
50
+ # 呼ばれるフックメソッドを作成します。
51
+ #
52
+ # 対象のメソッドはメソッド名で指定します。
53
+ #
54
+ # ==引数
55
+ # - ++method_name++: メソッド名
56
+ #
57
+ def cbefore(method_name, &block)
58
+ make_hook(:before, @target_class, method_name, &block)
59
+ end
12
60
 
13
- method_name = hook_method_name(method, hook_type)
14
- hook = block if block
15
- hook ||= default_hook(method, hook_type)
16
- @target_class.__send__ :define_method, method_name, hook
17
- self
18
- }
61
+ # インスタンスメソッドに対する after フックを作成
62
+ #
63
+ # ==詳細
64
+ # 引数で指定したインスタンスメソッドが実行される
65
+ # 直後に呼ばれるフックメソッドを作成します。
66
+ #
67
+ # 対象のメソッドはメソッド名で指定します。
68
+ #
69
+ # ==引数
70
+ # - ++method_name++: メソッド名
71
+ #
72
+ def after(method_name, &block)
73
+ make_hook(:after, @target, method_name, &block)
74
+ end
75
+
76
+ # クラスメソッドに対する after フックを作成
77
+ #
78
+ # ==詳細
79
+ # 引数で指定したクラスメソッドが実行される直後に
80
+ # 呼ばれるフックメソッドを作成します。
81
+ #
82
+ # 対象のメソッドはメソッド名で指定します。
83
+ #
84
+ # ==引数
85
+ # - ++method_name++: メソッド名
86
+ #
87
+ def cafter(method_name, &block)
88
+ make_hook(:after, @target_class, method_name, &block)
89
+ end
90
+
91
+ # インスタンスメソッドに対するスタブメソッドを作成
92
+ #
93
+ # ==詳細
94
+ # 引数で指定したインスタンスメソッドの代わりに呼ばれる
95
+ # 代替メソッドを作成します。
96
+ #
97
+ # 対象のメソッドはメソッド名で指定します。
98
+ #
99
+ # ==引数
100
+ # - ++method_name++: メソッド名
101
+ #
102
+ def stub(method_name, &block)
103
+ make_stub(@target, method_name, &block)
104
+ end
105
+
106
+ # クラスメソッドに対するスタブを作成
107
+ #
108
+ # ==詳細
109
+ # 引数で指定したクラスメソッドの代わりに呼ばれる代替
110
+ # メソッドを作成します。
111
+ #
112
+ # 対象のメソッドはメソッド名で指定します。
113
+ #
114
+ # ==引数
115
+ # - ++method_name++: メソッド名
116
+ #
117
+ def cstub(method_name, &block)
118
+ make_stub(@target_class, method_name, &block)
19
119
  end
20
120
 
21
- def stub(method, &block)
121
+ # インスタンスメソッドを書き戻す
122
+ #
123
+ # ==詳細
124
+ # 引数で指定したメソッドに対して行った操作を元に戻します。
125
+ #
126
+ # 基本的に、第一引数にメソッド名、第二引数に戻したい操作の
127
+ # 種類を指定します。
128
+ #
129
+ # たとえば、++foo++ というメソッドに対して ++before++
130
+ # フックを作成した、という操作を戻したい場合は、
131
+ #
132
+ # stub_a.restore(:foo, :before)
133
+ #
134
+ # のように指定します。
135
+ # 第一引数のメソッドに対して、戻したい操作の種類が複数ある
136
+ # 場合は、
137
+ #
138
+ # stub_a.restore(:foo, :before, :after)
139
+ #
140
+ # のように続けて指定することもできます。
141
+ #
142
+ # 逆に第二引数を省略した場合は、第一引数で指定したメソッドに
143
+ # 対して行ったすべての種類の操作を戻します。
144
+ #
145
+ # 操作したメソッドがひとつだけの場合で、かつ操作をすべて
146
+ # 戻して構わない場合は、引数を省略することもできます。
147
+ #
148
+ # ==引数
149
+ # - ++method_name++: メソッド名
150
+ # - ++types++: 操作の種類
151
+ #
152
+ def restore(method_name=nil, *types)
153
+ restore_hooks(@target, method_name, *types)
154
+ end
155
+
156
+ # クラスメソッドを書き戻す
157
+ #
158
+ # ==詳細
159
+ # ++restore++ がインスタンスメソッドに対する操作であるのに
160
+ # 対し、++crestore++ はクラスメソッドを操作の対象にします。
161
+ #
162
+ # 詳細については、++restore++ の説明を参照してください。
163
+ #
164
+ def crestore(method_name=nil, *types)
165
+ restore_hooks(@target_class, method_name, *types)
166
+ end
167
+
168
+ # すべてのインスタンスメソッドを書き戻す
169
+ #
170
+ # ==詳細
171
+ # インスタンスメソッドに対するすべての操作を書き戻します。
172
+ #
173
+ def restore_all
174
+ restore_all_hooks(@target)
175
+ end
176
+
177
+ # すべてのクラスメソッドを書き戻す
178
+ #
179
+ # ==詳細
180
+ # クラスメソッドに対するすべての操作を書き戻します。
181
+ #
182
+ def crestore_all
183
+ restore_all_hooks(@target_class)
184
+ end
185
+
186
+
187
+ private
188
+ METHOD_TYPES = [
189
+ :before,
190
+ :after,
191
+ :stub,
192
+ :origin,
193
+ ]
194
+ private_constant :METHOD_TYPES
195
+
196
+ def make_hook(hook_type, target, method, &block)
197
+ make_hook_points(target, method)
198
+
199
+ method_name = hook_method_name(method, hook_type)
200
+ hook = block if block
201
+ hook ||= default_hook(method, hook_type)
202
+ target.__send__ :define_method, method_name, hook
203
+ self
204
+ end
205
+
206
+ def make_stub(target, method, &block)
22
207
  raise ArgumentError, "No block" unless block
23
- make_hook_points(method)
208
+ make_hook_points(target, method)
24
209
 
25
210
  method_name = hook_method_name(method, :stub)
26
- @target_class.__send__ :define_method, method_name, block
211
+ target.__send__ :define_method, method_name, block
27
212
  self
28
213
  end
29
214
 
30
- def restore(method=nil, *types)
215
+ def restore_hooks(target, method=nil, *types)
31
216
  if method.nil?
32
- hooks = defined_hooks
217
+ hooks = defined_hooks(target)
33
218
  method = hooks.keys.first if hooks.keys.size == 1
34
219
  end
35
220
  raise "Method name to be restored is required." if method.nil?
@@ -41,38 +226,29 @@ class StubA
41
226
 
42
227
  types.each do |type|
43
228
  method_name = hook_method_name(method, type)
44
- next unless @target_class.method_defined? method_name
45
- @target_class.__send__ :remove_method, method_name
229
+ next unless target.method_defined? method_name
230
+ target.__send__ :remove_method, method_name
46
231
  end
47
232
 
48
- hooks = defined_hooks
233
+ hooks = defined_hooks(target)
49
234
  if hooks[method.to_s].size == 1 and
50
235
  hooks[method.to_s].first == 'origin'
51
236
  origin = hook_method_name(method, :origin)
52
- @target_class.__send__ :alias_method, method, origin
53
- @target_class.__send__ :remove_method, origin
237
+ target.__send__ :alias_method, method, origin
238
+ target.__send__ :remove_method, origin
54
239
  end
55
240
  end
56
241
 
57
- def restore_all
58
- defined_hooks.each do |method, types|
242
+ def restore_all_hooks(target)
243
+ defined_hooks(target).each do |method, types|
59
244
  types.each do |type|
60
245
  name = hook_method_name(method, type)
61
- next unless @target_class.method_defined? name
62
- @target_class.__send__ :alias_method, method, name if type == 'origin'
63
- @target_class.__send__ :remove_method, name
246
+ next unless target.method_defined? name
247
+ target.__send__ :alias_method, method, name if type == 'origin'
248
+ target.__send__ :remove_method, name
64
249
  end
65
250
  end
66
251
  end
67
-
68
- private
69
- METHOD_TYPES = [
70
- :before,
71
- :after,
72
- :stub,
73
- :origin,
74
- ]
75
- private_constant :METHOD_TYPES
76
252
 
77
253
  def hook_method_name(method, type)
78
254
  "===>(stub_a) #{type}-#{method}"
@@ -84,12 +260,12 @@ class StubA
84
260
  end
85
261
  end
86
262
 
87
- def make_hook_points(method_name)
263
+ def make_hook_points(target, method_name)
88
264
  methods = hook_method_names(method_name)
89
- return if @target_class.method_defined? methods[:origin]
265
+ return if target.method_defined? methods[:origin]
90
266
 
91
- @target_class.__send__ :alias_method, methods[:origin], method_name
92
- @target_class.__send__ :define_method, method_name, ->(*args, &block) {
267
+ target.__send__ :alias_method, methods[:origin], method_name
268
+ target.__send__ :define_method, method_name, ->(*args, &block) {
93
269
  if respond_to? methods[:before]
94
270
  __send__ methods[:before], ARGS[:before].new(method_name, args), &block
95
271
  end
@@ -102,20 +278,19 @@ class StubA
102
278
  end
103
279
 
104
280
  if respond_to? methods[:after]
105
- __send__ methods[:after], ARGS[:after].new(method_name, val)
281
+ __send__ methods[:after], ARGS[:after].new(method_name, args, val)
106
282
  end
107
283
 
108
284
  val
109
285
  }
110
286
  end
111
287
 
112
- def defined_hooks
113
- re = /\A===>\(stub_a\) (before|after|stub|origin)-(.+)\z/
114
- @target_class.instance_methods.each_with_object({}) {|name, h|
115
- if name.to_s =~ re
116
- h[$2] ||= []
117
- h[$2] << $1
118
- end
288
+ def defined_hooks(target)
289
+ re = /\A===>\(stub_a\) (#{METHOD_TYPES.join('|')})-(.+)\z/
290
+ target.instance_methods.each_with_object({}) {|name, h|
291
+ next if name.to_s !~ re
292
+ h[$2] ||= []
293
+ h[$2] << $1
119
294
  }
120
295
  end
121
296
 
@@ -129,26 +304,26 @@ class StubA
129
304
  end
130
305
 
131
306
  def default_before_hook(method)
132
- ->(method, *args, &block) {
133
- puts "[#{Time.now}] call `#{method}' (#{self.inspect})"
134
- puts "args: #{args.inspect}" if args.size > 0
307
+ ->(arg, &block) {
308
+ puts "[#{Time.now}] call `#{arg.method_name}' (#{self.inspect})"
309
+ puts "args: #{arg.args.inspect}" if arg.args.size > 0
135
310
  }
136
311
  end
137
312
 
138
313
  def default_after_hook(method)
139
314
  before_method = hook_method_name(method, :before)
140
- ->(method, val) {
315
+ ->(arg) {
141
316
  unless respond_to? before_method
142
- puts "[#{Time.now}] call `#{method}' (#{self.inspect})"
317
+ puts "[#{Time.now}] call `#{arg.method_name}' (#{self.inspect})"
143
318
  end
144
- puts "return: #{val.inspect}"
319
+ puts "return: #{arg.return_value.inspect}"
145
320
  }
146
321
  end
147
322
 
148
323
  ARGS = {
149
324
  before: Struct.new(:method_name, :args),
150
325
  stub: Struct.new(:method, :args),
151
- after: Struct.new(:method_name, :return_value),
326
+ after: Struct.new(:method_name, :args, :return_value),
152
327
  }
153
328
  private_constant :ARGS
154
329
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stub_a
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - 60ml