Skip to content
This repository

rhook - Easily drive AOP & hacking existing library with Ruby

tree: df50e3e33a

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 examples
Octocat-spinner-32 lib
Octocat-spinner-32 spec
Octocat-spinner-32 .document
Octocat-spinner-32 .gitignore
Octocat-spinner-32 .yardopts
Octocat-spinner-32 LICENSE
Octocat-spinner-32 README.rdoc
Octocat-spinner-32 Rakefile
Octocat-spinner-32 VERSION
Octocat-spinner-32 rhook.gemspec
README.rdoc

rhook - Easily drive AOP & hacking existing library with Ruby

Summary

  • 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.

Install

gem install rhook

Basic Usage

step. Example code

class TargetBasic
  def greeting
    my_name = "Mike"
    your_name = "Dan"
    hello(your_name) + "I am #{my_name}."
  end

  def hello(name)
    "Hello, #{name}. "
  end
end #/TargetBasic

that behaves as:

t = TargetBasic.new
t.greeting.should == "Hello, Dan. I am Mike."

step. Insert hook point in TargetBasic

require "rhook"      # <==   load library.

class TargetBasic
  def greeting
    my_name = _rhook.does(:my_name) { "Mike"; }         # <==  my_name = "Mike"
    your_name = "Dan"
    _rhook.to.hello(your_name) + "I am #{my_name}."         # <==  hello(your_name) + "I am #{my_name}."
  end

  def hello(name)
    "Hello, #{name}. "
  end
end #/TargetBasic

step. Add hook from outside, and change behavior.

t = TargetBasic.new
t._rhook.bind(:hello) { |inv|
  inv.args[0] = "Jenkins"     # change first argument.
  inv.call
}
t._rhook.bind(:my_name) { |inv|
  "Katherine"     # change return value.
}

that behaves as:

t.greeting.should == "Hello, Jenkins. I am Katherine."
                             ~~~~~~~       ~~~~~~~~~

More Basic TIPs

about '_rhook'

Once you require 'rhook', any objects has '_rhook' method to access any rhook services. (that returns {RHook::RHookService} object.)

any_object = Object.new
any_object._rhook.RHOOK_METHOD

See rubydoc.info/github/kaorukobo/rhook/master/RHook/RHookService

What is 'inv' ?

{RHook::Invocation} object, that contains:

  • call() method to proceed method invocation.

  • receiver, arguments/blcoks passed to method, and the other informations. See {RHook::Invocation}.

See rubydoc.info/github/kaorukobo/rhook/master/RHook/Invocation

If you want 'bind' to not only an object, but any instances of class:

TargetBasic._rhook.bind(:hello) { |inv| ...

If you want to HACK exisitng methods, use '_rhook.hack':

for the paticular instance:

t = Time.now
t._rhook.hack(:to_s) do |inv|
  "haha! I hacked to_s."
end
t.to_s.should == "haha! I hacked."

for entire class:

Time._rhook.hack(:to_s) do |inv|
  "haha! I hacked to_s."
end
(Time.now).to_s.should == "haha! I hacked to_s."

for class method:

Time._rhook.hack(:now) do |inv|
  "haha! you cannot get time."
end
Time.now.should == "haha! you cannot get time."

More Usage …

Please see spec: github.com/kaorukobo/rhook/blob/master/spec/rhook_spec.rb

Practical Examples

1. Log Buffer

Log Buffer allows you to capture any messages written to Logger and keep in buffer.

For example, you can examine the target program's log messages in testing code.

github.com/kaorukobo/rhook/blob/master/spec/examples/log_buffer_example_spec.rb

Note on Patches/Pull Requests

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don't break it in a future version unintentionally.

  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)

  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright © 2010 Kaoru Kobo. See LICENSE for details.

Something went wrong with that request. Please try again.