rhook 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --no-private
2
+ --title "rhook"
data/README.rdoc CHANGED
@@ -1,9 +1,16 @@
1
1
  = rhook - Easily drive AOP & hacking existing library with Ruby
2
2
 
3
+ - Homepage & Source -- http://github.com/kaorukobo/rhook
4
+ - Download -- http://rubygems.org/gems/rhook
5
+ - API Documentation (RDoc) -- http://rubydoc.info/github/kaorukobo/rhook/master/frames
6
+
7
+ == Summary
8
+
3
9
  - You can provide hook point in your code,
4
10
  - and can customize its behavior from outside.
5
11
  - Also you can 'hack' (== injecting hook point from outside) any methods in existing code.
6
12
 
13
+
7
14
  == Install
8
15
 
9
16
  gem install rhook
@@ -65,20 +72,21 @@
65
72
 
66
73
  === about '_rhook'
67
74
 
68
- Once you require 'rhook', any objects has '_rhook' method to access any rhook services. (that returns RHook::RHookService object.)
75
+ Once you require 'rhook', any objects has '_rhook' method to access any rhook services. (that returns {RHook::RHookService} object.)
69
76
 
70
77
  any_object = Object.new
71
78
  any_object._rhook.RHOOK_METHOD
72
79
 
80
+ See http://rubydoc.info/github/kaorukobo/rhook/master/RHook/RHookService
81
+
73
82
  === What is 'inv' ?
74
83
 
75
- RHook::Invocation object, that contains:
84
+ {RHook::Invocation} object, that contains:
76
85
 
77
86
  - call() method to proceed method invocation.
78
- - receiver
79
- - arguments passed to method
80
- - blocks passed to method
81
- - returned value by call()
87
+ - receiver, arguments/blcoks passed to method, and the other informations. See {RHook::Invocation}.
88
+
89
+ See http://rubydoc.info/github/kaorukobo/rhook/master/RHook/Invocation
82
90
 
83
91
  === If you want 'bind' to not only an object, but any instances of class:
84
92
 
@@ -113,6 +121,16 @@ for class method:
113
121
 
114
122
  Please see spec: http://github.com/kaorukobo/rhook/blob/master/spec/rhook_spec.rb
115
123
 
124
+ == Practical Examples
125
+
126
+ === 1. Log Buffer
127
+
128
+ Log Buffer allows you to capture any messages written to Logger and keep in buffer.
129
+
130
+ For example, you can examine the target program's log messages in testing code.
131
+
132
+ http://github.com/kaorukobo/rhook/blob/master/spec/examples/log_buffer_example_spec.rb
133
+
116
134
  == ...
117
135
 
118
136
  === Note on Patches/Pull Requests
data/Rakefile CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'rubygems'
2
2
  require 'rake'
3
3
 
4
+ require "logger"
5
+ log = Logger.new(STDERR)
6
+
4
7
  begin
5
8
  require 'jeweler'
6
9
  Jeweler::Tasks.new do |gem|
@@ -11,6 +14,8 @@ begin
11
14
  gem.homepage = "http://github.com/kaorukobo/rhook"
12
15
  gem.authors = ["Kaoru Kobo"]
13
16
  gem.add_development_dependency "rspec", ">= 1.2.9"
17
+ gem.add_development_dependency "yard", "~> 0.6.0"
18
+ gem.has_rdoc = "yard"
14
19
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
20
  end
16
21
  Jeweler::GemcutterTasks.new
@@ -34,12 +39,11 @@ task :spec => :check_dependencies
34
39
 
35
40
  task :default => :spec
36
41
 
37
- require 'rake/rdoctask'
38
- Rake::RDocTask.new do |rdoc|
39
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
-
41
- rdoc.rdoc_dir = 'rdoc'
42
- rdoc.title = "rhook #{version}"
43
- rdoc.rdoc_files.include('README*')
44
- rdoc.rdoc_files.include('lib/**/*.rb')
42
+ begin
43
+ gem "yard"
44
+ require "yard"
45
+ YARD::Rake::YardocTask.new do |t|
46
+ end
47
+ rescue Gem::LoadError
48
+ log.warn "Install YARD to generate document."
45
49
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.5
1
+ 0.1.6
@@ -0,0 +1,34 @@
1
+ require "socket"
2
+
3
+ require "rubygems"
4
+ require "rhook"
5
+
6
+ # Trace TCPSocket output data.
7
+ TCPSocket._rhook.hack(:write) do |inv|
8
+ STDERR.print("> ", inv.args[0].inspect, "\n")
9
+ inv.call
10
+ end
11
+
12
+ # Trace TCPSocket input data.
13
+ TCPSocket._rhook.hack(:read) do |inv|
14
+ inv.call
15
+ STDERR.print("< ", inv.returned.inspect, "\n")
16
+ inv.returned
17
+ end
18
+
19
+
20
+ require "rack"
21
+ require "rack/handler/webrick"
22
+
23
+ th = Thread.start {
24
+ Rack::Handler::WEBrick.run(lambda { |env|
25
+ [200, {}, []]
26
+ }, :Port => 9292)
27
+ }
28
+ sleep 1
29
+
30
+ sock = TCPSocket.new("localhost", 9292)
31
+ sock.print("GET / HTTP/1.0\n\n")
32
+ sock.flush
33
+
34
+ sock.read
data/lib/rhook.rb CHANGED
@@ -1,4 +1,7 @@
1
1
  module RHook
2
+ # @private
3
+ # The registry contains information globally shared. (like cache)
4
+ # You don't need to use this class.
2
5
  class Registry
3
6
  attr_reader :class_cached_flag_map
4
7
  def initialize
@@ -6,19 +9,44 @@ module RHook
6
9
  end
7
10
  end
8
11
 
12
+ # @private
13
+ # Get global +Registry+ object.
9
14
  def self.registry
10
15
  @registry ||= Registry.new
11
16
  end
12
17
 
18
+ # Most important class on rhook.
19
+ #
20
+ # If you call obj._rhook, it returns a RHookService object bound to +obj+.
13
21
  class RHookService
22
+ # @private
14
23
  attr_reader :hooks_map
15
24
 
25
+ # @private
16
26
  def initialize(obj)
17
27
  @obj = obj
18
28
  @hooks_map = {}
19
29
  @class_cached_hooks_map = {} if Class === @obj
20
30
  end
21
31
 
32
+ # Returns the object bound to this RHookService.
33
+ # ( +obj+ of +obj._rhook+ )
34
+ def bound_object
35
+ @obj
36
+ end
37
+
38
+ # ========================================================================
39
+ # @group Methods for hook-side(outside)
40
+ # ========================================================================
41
+
42
+ # Add hook to the {#bound_object}. If it is a kind of Class, the hook is affected to all instance & subclasses of the class.
43
+ #
44
+ # @param [Symbol] name hook-point's name (commonly equals to method name)
45
+ # @option opt [true] :disable Create hook but make disabled. (by default, automatically enabled.)
46
+ # @yield [inv] The hook block.
47
+ # @yieldparam [Invocation] inv
48
+ # @yieldreturn The result value. (Returned value of called method.)
49
+ # @return [Hook] Created hook.
22
50
  def bind(name, opt = {}, &block)
23
51
  hook = Hook.new
24
52
  hook.hook_proc = block
@@ -29,6 +57,15 @@ module RHook
29
57
  hook
30
58
  end
31
59
 
60
+ # Injects hook-point (hack) to the paticular method in {#bound_object}, and add hook same as {#bind}.
61
+ #
62
+ # The hook-point injection is done by 'alias' method.
63
+ # If the hook-point is already injected, this just does {#bind}.
64
+ #
65
+ # @param [Symbol] name The name of method to hack.
66
+ # @yield [inv]
67
+ # @return [Hook]
68
+ # @see #bind See #bind for other param/return.
32
69
  def hack(name, opt = {}, &block)
33
70
  success = false
34
71
  if Class === @obj
@@ -44,13 +81,21 @@ module RHook
44
81
  bind(name, opt, &block)
45
82
  end
46
83
 
84
+ # @group Methods for hook-side(outside)
85
+ #
86
+ # Unbind all hooks bound to {#bound_object}.
87
+ # @return [self]
47
88
  def unbind_all
48
89
  @hooks_map.clear
49
90
  @class_cached_hooks_map.clear
91
+ self
50
92
  end
51
93
 
52
- # nodoc:
53
- # Proxy class for 'to'
94
+ # ========================================================================
95
+ # @endgroup
96
+ # ========================================================================
97
+
98
+ # @private
54
99
  class Caller
55
100
  def initialize(rhook, opt)
56
101
  @rhook = rhook
@@ -62,13 +107,22 @@ module RHook
62
107
  end
63
108
  end #/Caller
64
109
 
65
- # ================================================================
66
- # Target-side methods:
67
-
110
+ # ========================================================================
111
+ # @group Methods for target-side (for providing hook-point)
112
+ # ========================================================================
113
+
114
+ # Wraps {#bound_object}'s method call to be hookable.
115
+ #
116
+ # @example
117
+ # _rhook.to.method_name(arg1, arg2)
118
+ #
119
+ # @option opt [Hash] :hint Hint values used through {Invocation#hint}.
120
+ # @return Proxy to call method.
68
121
  def to(opt = {})
69
122
  Caller.new(self, opt)
70
123
  end
71
124
 
125
+ # @private
72
126
  def call_method(name, method_name, args, block, opt = {})
73
127
  hooks = concat_hooks([], name)
74
128
  hooks.empty? and return @obj.__send__(method_name, *args, &block)
@@ -84,6 +138,15 @@ module RHook
84
138
  inv.proceed()
85
139
  end
86
140
 
141
+ # Wraps the code block to be hookable.
142
+ #
143
+ # @example
144
+ # _rhook.does(:hook_name) { do_something; }
145
+ #
146
+ # @param [Symbol] name The hook-point's name specified on {#bind}.
147
+ # @option opt [Hash] :hint Hint values used through {Invocation#hint}.
148
+ # @yield The code block to be hooked.
149
+ # @return The result of code block. (Replaced if it is changed by hook.)
87
150
  def does(name, opt = {}, &block)
88
151
  hooks = concat_hooks([], name)
89
152
  hooks.empty? and return yield
@@ -99,6 +162,18 @@ module RHook
99
162
  inv.proceed()
100
163
  end
101
164
 
165
+ # Wraps the defined method to be hookable.
166
+ #
167
+ # If possible, using {#to} is recommended than {#on_method}, because if the subclass override the hookable method, the subclasse's code become out of hook target.
168
+ #
169
+ # @example
170
+ # on_method :method_name
171
+ #
172
+ # @overload on_method(*names, opt = {})
173
+ # @param [Symbol] names The method name(s).
174
+ # @option opt [Boolean] :ifdef If true, it doesn't raise error whenever the method is not defined.
175
+ # @raise [NameError] If the method is not defined.
176
+ # @return [Boolean] When :ifdef => true, returns sucess or not, otherwise always true.
102
177
  def on_method(*names_and_opt)
103
178
  success = true
104
179
 
@@ -122,9 +197,11 @@ module RHook
122
197
  success
123
198
  end
124
199
 
125
- # ================================================================
126
- # Internal methods:
127
-
200
+ # ========================================================================
201
+ # @endgroup
202
+ # ========================================================================
203
+
204
+ # @private
128
205
  def concat_hooks(dest, name)
129
206
  if Class === @obj
130
207
  concat_class_hooks(dest, name)
@@ -135,6 +212,7 @@ module RHook
135
212
  dest
136
213
  end
137
214
 
215
+ # @private
138
216
  def concat_class_hooks(dest, name)
139
217
  # use cached one if available
140
218
  if RHook.registry.class_cached_flag_map[name]
@@ -145,7 +223,7 @@ module RHook
145
223
  end
146
224
 
147
225
  hooks = []
148
-
226
+
149
227
  # collect hooks including ancestor classes
150
228
  begin
151
229
  concat_hooks_internal(hooks, name)
@@ -168,25 +246,39 @@ module RHook
168
246
  dest.concat(hooks)
169
247
  end
170
248
 
249
+ # @private
171
250
  def concat_hooks_internal(dest, name)
172
251
  hooks = @hooks_map[name]
173
252
  hooks and dest.concat(hooks)
174
253
  end
175
254
  end #/RHookService
176
255
 
256
+ # The object contains the invocation information.
257
+ #
258
+ # @attr_reader [Object] target The target object that the hook is applied. (Usually same to {#receiver})
259
+ # @attr_reader [Object] receiver The receiver object of this method invocation.
260
+ # @attr [Array<Object>] args The arguments given to the method invocation.
261
+ # @attr [Proc] block The block given to the method invocation
262
+ # @attr_reader [Object] returned The returned value by the method invocation. (Don't set this. To change it, just return by the alternative value from the hook procedure.)
263
+ # @attr_reader [Array<Hook>] hooks (Internally used) The applied hooks on this invocation.
264
+ # @attr [Proc] target_proc (Internally used) The procedure to execute the target method/procedure.
265
+ # @attr [Hash] hint Hint data given by {RHookService#does} / {RHookService#to}.
177
266
  class Invocation < Struct.new(:target, :receiver, :args, :block, :returned, :hooks, :target_proc, :hint)
267
+ # @private
178
268
  def initialize
179
269
  @hook_index = 0
180
270
  end
181
271
 
272
+ # Proceed to execute the next one on hooks-chain. If no more hooks, execute the target method/procedure.
273
+ # @return The returned value from the target method/procedure. (may changed by hook)
182
274
  def proceed
183
275
  hook = hooks[@hook_index]
184
276
  # -- If no more hook was found, calls target procedure and return
185
- hook or return target_proc.call(*args, &block)
277
+ hook or return self.returned = target_proc.call(*args, &block)
186
278
  # -- Set hook pointer to next, then call next hook
187
279
  @hook_index += 1
188
280
  begin
189
- hook.call(self)
281
+ self.returned = hook.call(self)
190
282
  ensure
191
283
  @hook_index -= 1
192
284
  end
@@ -195,15 +287,26 @@ module RHook
195
287
  alias call proceed
196
288
  end #/Invocation
197
289
 
290
+ # The registered hook instance returned by #{RHookService#bind}.
198
291
  class Hook
292
+ # Whether this hook is enabled.
293
+ # @return [Boolean]
199
294
  attr_accessor :enabled
295
+ # The hook procedure registered by {RHookService#bind}.
296
+ # @return [Proc]
200
297
  attr_accessor :hook_proc
201
298
 
299
+ # @private
202
300
  def call(inv)
203
301
  @enabled or return inv.proceed()
204
302
  hook_proc.call(inv)
205
303
  end
206
304
 
305
+ # Enable this hook.
306
+ # @overload enable()
307
+ # @overload enable(&block)
308
+ # @yield If block was given, the hook is enabled only within the given code block. (Note: This is not thread-safe.)
309
+ # @return [self]
207
310
  def enable(&block)
208
311
  @enabled = true
209
312
  if block_given?
@@ -216,31 +319,47 @@ module RHook
216
319
  self
217
320
  end
218
321
 
322
+ # Disable this hook.
323
+ # @return [self]
219
324
  def disable
220
325
  @enabled = false
221
326
  self
222
327
  end
223
328
  end #/Hook
224
329
 
330
+ #
225
331
  class ::Object
332
+ # Get {RHook::RHookService} object bound to this object.
333
+ # @return [RHook::RHookService]
226
334
  def _rhook
227
335
  @_rhook ||= RHook::RHookService.new(self)
228
336
  end
229
337
 
338
+ # @private
230
339
  def _has_rhook?
231
340
  @_rhook ? true : false
232
341
  end
233
342
  end
234
343
 
344
+ # Object to group the hooks for the certain purpose.
345
+ # You can enable/disable the grouped hooks at once.
346
+ #
347
+ # Don't instantiate this class. Use {RHook.group} method.
235
348
  class HookGroup
349
+ # @private
236
350
  def initialize
237
351
  @hooks = []
238
352
  end
239
353
 
354
+ # Add a new hook to this group.
355
+ # @return [self]
240
356
  def add(hook)
241
357
  @hooks << hook
358
+ self
242
359
  end
243
360
 
361
+ # Add any hooks to this group that was registered by #{RHookService#bind} in the given block code.
362
+ # @return [self]
244
363
  def wrap(&block)
245
364
  group_stack = (Thread.current["rhook_group"] ||= [])
246
365
  group_stack << self
@@ -252,6 +371,9 @@ module RHook
252
371
  self
253
372
  end
254
373
 
374
+ # Enable the hooks.
375
+ # @return [self]
376
+ # @see Hook#enable
255
377
  def enable(&block)
256
378
  @hooks.each do |h|
257
379
  h.enable
@@ -266,6 +388,9 @@ module RHook
266
388
  self
267
389
  end
268
390
 
391
+ # Disable the hooks.
392
+ # @return [self]
393
+ # @see Hook#disable
269
394
  def disable
270
395
  @hooks.each do |h|
271
396
  h.disable
@@ -273,13 +398,24 @@ module RHook
273
398
  self
274
399
  end
275
400
 
401
+ # @private
276
402
  def self.add_to_current_groups(hook)
277
- (Thread.current["rhook_group"] || []).each do |group|
403
+ (Thread.current["rhook_group"] || []).each do |group|
278
404
  group.add(hook)
279
405
  end
280
406
  end
281
407
  end #/HookGroup
282
408
 
409
+ # Create the {HookGroup}, and add any hooks to this group that was registered by #{RHookService#bind} in the given block code.
410
+ #
411
+ # @example
412
+ # XXX_feature_for_library = RHook.group {
413
+ # Target._rhook.bind(...) {...}
414
+ # Target2._rhook.bind(...) {...}
415
+ # }
416
+ # XXX_feature_for_library.disable
417
+ #
418
+ # @return [HookGroup]
283
419
  def self.group(&block)
284
420
  HookGroup.new.wrap(&block)
285
421
  end
data/rhook.gemspec CHANGED
@@ -1,44 +1,48 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rhook}
8
- s.version = "0.1.5"
8
+ s.version = "0.1.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kaoru Kobo"]
12
- s.date = %q{2010-11-12}
12
+ s.date = %q{2010-12-01}
13
13
  s.description = %q{You can provide hook point in your code, and can customize its behavior from outside. Also you can 'hack' (== injecting hook point from outside) any methods in existing code.}
14
14
  s.email = %q{}
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.rdoc"
17
+ "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
21
- ".gitignore",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "VERSION",
26
- "lib/rhook.rb",
27
- "rhook.gemspec",
28
- "spec/rhook_minor_spec.rb",
29
- "spec/rhook_spec.rb",
30
- "spec/spec.opts",
31
- "spec/spec_helper.rb"
21
+ ".yardopts",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "examples/log_socket_data.rb",
27
+ "lib/rhook.rb",
28
+ "rhook.gemspec",
29
+ "spec/examples/log_buffer_example_spec.rb",
30
+ "spec/rhook_minor_spec.rb",
31
+ "spec/rhook_spec.rb",
32
+ "spec/spec.opts",
33
+ "spec/spec_helper.rb"
32
34
  ]
35
+ s.has_rdoc = %q{yard}
33
36
  s.homepage = %q{http://github.com/kaorukobo/rhook}
34
- s.rdoc_options = ["--charset=UTF-8"]
35
37
  s.require_paths = ["lib"]
36
38
  s.rubygems_version = %q{1.3.7}
37
39
  s.summary = %q{Easily drive AOP & hacking existing library with Ruby}
38
40
  s.test_files = [
41
+ "examples/log_socket_data.rb",
42
+ "spec/examples/log_buffer_example_spec.rb",
39
43
  "spec/rhook_minor_spec.rb",
40
- "spec/rhook_spec.rb",
41
- "spec/spec_helper.rb"
44
+ "spec/rhook_spec.rb",
45
+ "spec/spec_helper.rb"
42
46
  ]
43
47
 
44
48
  if s.respond_to? :specification_version then
@@ -47,11 +51,14 @@ Gem::Specification.new do |s|
47
51
 
48
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
53
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
54
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
50
55
  else
51
56
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
57
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
52
58
  end
53
59
  else
54
60
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
61
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
55
62
  end
56
63
  end
57
64
 
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "rhook examples" do
4
+ describe "log buffer (hack Logger)" do
5
+ require "logger"
6
+
7
+ # Captures any messages written to Logger and keep in buffer.
8
+ # You can read captured messages by LogBuffer#get
9
+ # or LogBuffer##pull ( also clears buffer ).
10
+ class LogBuffer
11
+ def initialize
12
+ @buf = ""
13
+ # Any log messages are passed to Logger#format_message. Hack it!!
14
+ Logger._rhook.hack(:format_message) do |inv|
15
+ result = inv.call
16
+ @buf << result
17
+ result
18
+ end
19
+ end
20
+
21
+ def clear
22
+ @buf = ""
23
+ end
24
+
25
+ def get
26
+ @buf
27
+ end
28
+
29
+ def pull
30
+ result = get()
31
+ clear()
32
+ result
33
+ end
34
+ end #/LogBuffer
35
+
36
+ # The example application to test.
37
+ # You cannot know whether it success or failed, (by return value or exception)
38
+ # ... it only logs.
39
+ class TargetApp
40
+ def initialize
41
+ @log = Logger.new(STDERR)
42
+ end
43
+
44
+ def success
45
+ @log.info "Success!"
46
+ end
47
+
48
+ def fail
49
+ @log.error "Failed!"
50
+ end
51
+ end
52
+
53
+ example "Use LogBuffer to write test" do
54
+ app = TargetApp.new
55
+
56
+ # start to capture log.
57
+ logbuf = LogBuffer.new
58
+
59
+ app.success
60
+ logbuf.pull.should match(/Success!/)
61
+
62
+ app.fail
63
+ logbuf.pull.should match(/Failed!/)
64
+ end
65
+ end
66
+ end
data/spec/rhook_spec.rb CHANGED
@@ -216,6 +216,51 @@ describe "rhook (advanced usage)" do
216
216
  end
217
217
  # ================================================================
218
218
 
219
+ # ========================================================================
220
+ describe "Invocation object" do
221
+ class Target
222
+ def invocation_object(*args, &block)
223
+ _rhook.to(:hint => {:hintkey => :hintval}).invocation_object_target(*args, &block)
224
+ end
225
+
226
+ def invocation_object_target(*args, &block)
227
+ :returned_value
228
+ end
229
+ end #/Target
230
+
231
+ example "attributes" do
232
+ args = [1, 2]
233
+ block = lambda do
234
+
235
+ end
236
+
237
+ lambda { |called|
238
+ t = Target.new
239
+ t._rhook.bind(:invocation_object_target) { |inv|
240
+ # first hook
241
+ called.yes
242
+ inv.call()
243
+ inv.returned.should == :returned_value
244
+ :returned_value_hooked
245
+ }
246
+ t._rhook.bind(:invocation_object_target) { |inv|
247
+ # second hook
248
+ called.yes
249
+ inv.args.should == args
250
+ inv.block.should == block
251
+ inv.hint[:hintkey].should == :hintval
252
+ inv.receiver.should == t
253
+ inv.target.should == t
254
+ inv.returned.should be_nil
255
+ inv.call()
256
+ inv.returned.should == :returned_value_hooked
257
+ }
258
+ t.invocation_object(*args, &block)
259
+ }.should calls_hook(:times => 2)
260
+ end
261
+ end
262
+ # ========================================================================
263
+
219
264
  end
220
265
 
221
266
  # ================================================================
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'rubygems'
2
- gem 'rspec'
2
+ gem 'rspec', "< 2.0"
3
3
 
4
4
  $LOAD_PATH.unshift(File.dirname(__FILE__))
5
5
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
@@ -10,3 +10,45 @@ require 'spec/autorun'
10
10
  Spec::Runner.configure do |config|
11
11
 
12
12
  end
13
+
14
+ # ========================================================================
15
+ # Defines custom matcher to test the hook was called.
16
+
17
+ module ::Spec::Matchers
18
+ class HookCalledMatcher
19
+ def initialize(opt)
20
+ @times = opt[:times]
21
+ @count = 0
22
+ end
23
+
24
+ def yes
25
+ @count += 1
26
+ end
27
+
28
+ def matches?(block)
29
+ block.call(self)
30
+ if @times
31
+ begin
32
+ @count.should == @times
33
+ rescue
34
+ @times_msg = " (Exactly called count: #{$!})"
35
+ false
36
+ end
37
+ else
38
+ @count > 0
39
+ end
40
+ end
41
+
42
+ def failure_message
43
+ "Expected the hook to be called.#{@times_msg}"
44
+ end
45
+
46
+ def negative_failure_message
47
+ "Expected the hook not to be called.#{@times_msg}"
48
+ end
49
+ end
50
+
51
+ def calls_hook(opt = {})
52
+ HookCalledMatcher.new(opt)
53
+ end
54
+ end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhook
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 23
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 5
9
- version: 0.1.5
9
+ - 6
10
+ version: 0.1.6
10
11
  platform: ruby
11
12
  authors:
12
13
  - Kaoru Kobo
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-11-12 00:00:00 +09:00
18
+ date: 2010-12-01 00:00:00 +09:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,6 +26,7 @@ dependencies:
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 13
28
30
  segments:
29
31
  - 1
30
32
  - 2
@@ -32,6 +34,22 @@ dependencies:
32
34
  version: 1.2.9
33
35
  type: :development
34
36
  version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: yard
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 0
48
+ - 6
49
+ - 0
50
+ version: 0.6.0
51
+ type: :development
52
+ version_requirements: *id002
35
53
  description: You can provide hook point in your code, and can customize its behavior from outside. Also you can 'hack' (== injecting hook point from outside) any methods in existing code.
36
54
  email: ""
37
55
  executables: []
@@ -43,24 +61,26 @@ extra_rdoc_files:
43
61
  - README.rdoc
44
62
  files:
45
63
  - .document
46
- - .gitignore
64
+ - .yardopts
47
65
  - LICENSE
48
66
  - README.rdoc
49
67
  - Rakefile
50
68
  - VERSION
69
+ - examples/log_socket_data.rb
51
70
  - lib/rhook.rb
52
71
  - rhook.gemspec
72
+ - spec/examples/log_buffer_example_spec.rb
53
73
  - spec/rhook_minor_spec.rb
54
74
  - spec/rhook_spec.rb
55
75
  - spec/spec.opts
56
76
  - spec/spec_helper.rb
57
- has_rdoc: true
77
+ has_rdoc: yard
58
78
  homepage: http://github.com/kaorukobo/rhook
59
79
  licenses: []
60
80
 
61
81
  post_install_message:
62
- rdoc_options:
63
- - --charset=UTF-8
82
+ rdoc_options: []
83
+
64
84
  require_paths:
65
85
  - lib
66
86
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -68,6 +88,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
68
88
  requirements:
69
89
  - - ">="
70
90
  - !ruby/object:Gem::Version
91
+ hash: 3
71
92
  segments:
72
93
  - 0
73
94
  version: "0"
@@ -76,6 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
97
  requirements:
77
98
  - - ">="
78
99
  - !ruby/object:Gem::Version
100
+ hash: 3
79
101
  segments:
80
102
  - 0
81
103
  version: "0"
@@ -87,6 +109,8 @@ signing_key:
87
109
  specification_version: 3
88
110
  summary: Easily drive AOP & hacking existing library with Ruby
89
111
  test_files:
112
+ - examples/log_socket_data.rb
113
+ - spec/examples/log_buffer_example_spec.rb
90
114
  - spec/rhook_minor_spec.rb
91
115
  - spec/rhook_spec.rb
92
116
  - spec/spec_helper.rb
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC