Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 201 lines (143 sloc) 6.84 kb
e8bd2c3 @txus first commit
authored
1 #hijacker
2
3 A little gem that hijacks any ruby object and broadcasts all its activity
1f06388 @txus Finished custom Handlers support :)
authored
4 to a particular hijacker server. The server exposes a special handler object
5 which then does fun things with the received data!
6
7 For example, by now there is only one handler: Logger. This handler shows the
8 received activity in the server output with fancy logging-style colors. Could
9 be quite useful for those awfully long debugging afternoons!
10
11 Of course, you can write your own handlers to do whatever you want with the
12 data: maybe record how many arguments do your methods accept on average, log
13 into disk any method calls containing a certain type of argument... just be
14 creative! :)
15
16 (See the "Extending hijacker blabla" part below to know how to write your own
17 handlers)
e8bd2c3 @txus first commit
authored
18
78335c7 @txus Words
authored
19 Hijacker is tested with Ruby 1.8.7, 1.9.2, and JRuby 1.5.3. Unfortunately there
20 are some issues with Rubinius, mostly due to the metaprogramming stuff, which I
21 will definitely look into.
e8bd2c3 @txus first commit
authored
22
23 ##Install and configure
24
25 In your Gemfile:
26
27 gem 'hijacker'
28
29 If you are using Rails, you might want to put this configuration snippet in an
30 initializer or something (you can always put it in any other part of the code
31 otherwise, as long as it's before hijacking any object):
32
33 Hijacker.configure do
34 uri '<YOUR HIJACKER SERVER URI>'
35 end
36
37 And that's it! Oooor not. You have to spawn your server. In the command line:
38
1f06388 @txus Finished custom Handlers support :)
authored
39 hijacker <handler>
40
593a072 @txus Readme update.
authored
41 Where \<handler\> must be a registered handler (for now there is only 'logger').
1f06388 @txus Finished custom Handlers support :)
authored
42 So you type:
e8bd2c3 @txus first commit
authored
43
1f06388 @txus Finished custom Handlers support :)
authored
44 hijacker logger
45
46 And it will output the URI for this super fancy hijacker logging server.
47 *Remember this URI* and pass it to your configuration block!
e8bd2c3 @txus first commit
authored
48
78335c7 @txus Words
authored
49 If you have some custom handler, you should send me a pull request! In case you
50 don't want to, Hijacker automatically requires all ruby files inside these
51 paths:
52
53 ./.hijacker/**/**.rb
54 ~/.hijacker/**/**.rb
55
56 So you put your handlers in there and have fun! :)
57
e8bd2c3 @txus first commit
authored
58 Some options you can pass to the server command:
59
1f06388 @txus Finished custom Handlers support :)
authored
60 hijacker <handler> --port 1234 (spawn the server in port 1234 rather than 8787)
61
62 Specific handlers can accept specific options. Logger accepts these:
63
64 hijacker logger --without-timestamps (don't show the timestamps)
65 hijacker logger --without-classes (don't show the object classes)
e8bd2c3 @txus first commit
authored
66
67 ##Ok, and now for some hijacking action!
68
69 require 'hijacker' # You don't have to when using Bundler :)
70
71 class MyClass
72 def foo(bar, baz)
73 bar + baz
74 end
75 end
76
77 some_object = Object.new
78
79 # These are the important lines:
80
81 Hijacker.spy(some_object)
82 Hijacker.spy(MyClass)
83
84 instance = MyClass.new
85 instance.foo(3, 4)
86
1f06388 @txus Finished custom Handlers support :)
authored
87 Run this code and, given we are using the Logger handler, if you look at the server output, you'll see nothing less than...
e8bd2c3 @txus first commit
authored
88
89 <a nice timestamp> MyClass (Class) received :new and returned #<MyClass:0x000000874> (MyClass)
0dc8c0c @txus update readme
authored
90 <a nice timestamp> #<MyClass:0x000000874> (MyClass) received :foo with 3 (Fixnum), 4 (Fixnum) and returned 7 (Fixnum)
e8bd2c3 @txus first commit
authored
91
1f06388 @txus Finished custom Handlers support :)
authored
92 But in a nice set of colors.
93
e8bd2c3 @txus first commit
authored
94 If you want to un-hijack any object, just call #restore:
95
96 Hijacker.restore(MyClass)
97 Hijacker.restore(some_object)
98
99 If you don't want to have to remember every hijacked object you have to call
100 restore on it, you can just spy a particular object within the duration of a block:
101
102 Hijacker.spying(MyClass) do
103 # inside this block, MyClass will be spied
104 end
105 # here not anymore
106
107 Awesome! You can fine-tune your spying, for example by only spying on instance
108 methods or singleton methods only:
109
110 Hijacker.spy(MyClass, :only => :instance_methods) # or :singleton_methods
111
112 And, last but not least... you can specify a *particular hijacker server* for
113 a *particular object* you are spying on!
114
115 # All activity on MyClass and its instances will
116 # be sent to druby://localhost:9999
117 Hijacker.spy(MyClass, :uri => 'druby://localhost:9999')
118
119 # But for example, the activity of some_object will
120 # be sent to the default uri specified in the configuration
121 # back earlier (remember?)
122 Hijacker.spy(some_object)
123
124 Of course, you can specify a particular server uri for a block, with #spying:
125
126 Hijacker.spying(foo_object, :uri => 'druby://localhost:1234') do
127 # all the activity of foo_object inside this block
128 # will be sent to the hijacker server on druby://localhost:1234
129 end
1f06388 @txus Finished custom Handlers support :)
authored
130
131 ##Extending hijacker with moar handlers
132
133 It is really easy to write your own handlers. Why don't you write one and send
134 me a pull request? I mean now. What are you waiting for, why are you still reading?
135
78335c7 @txus Words
authored
136 Ok, maybe a bit of explanation on that. Handlers are automatically loaded from
137 here:
1f06388 @txus Finished custom Handlers support :)
authored
138
78335c7 @txus Words
authored
139 ./.hijacker/**/*.rb
140 ~/.hijacker/**/*.rb
1f06388 @txus Finished custom Handlers support :)
authored
141
78335c7 @txus Words
authored
142 They are automatically registered, so all you have to do is write them like this:
1f06388 @txus Finished custom Handlers support :)
authored
143
144 module Hijacker
145 class MyHandler < Handler # Yes, you have to subclass Hijacker::Handler!
146
147 # You must implement a class method named cli_options which must
148 # return a Trollop-friendly Proc, for command-line options parsing.
149 #
150 # These options can be accessed within the #handle method by calling
151 # the opts method.
152 #
153 def self.cli_options
154 Proc.new {
155 opt :without_foo, "Don't use foo to handle the method name"
156 opt :using_bar, "Use bar as much as you can"
157 }
158 end
159
160 # This is the most important method. This is what is called every time
161 # a method call is performed on a hijacked object. The received params
162 # look like this:
163 #
164 # method :foo
165 #
166 # args [{:inspect => '3', :class => 'Fixnum'},
167 # {:inspect => '"string"', :class => 'String'}]
78335c7 @txus Words
authored
168 #
169 # retval {:inspect => ':bar', :class => 'Symbol'}
170 # (note: retval will be nil if the method raised)
1f06388 @txus Finished custom Handlers support :)
authored
171 #
78335c7 @txus Words
authored
172 # raised {:inspect => 'oops', :class => 'StandardError'}
173 # (note: raised will be nil unless the method raised, obviously)
1f06388 @txus Finished custom Handlers support :)
authored
174 #
78335c7 @txus Words
authored
175 # object {:inspect => '#<MyClass:0x003457>', :class => 'MyClass'}
1f06388 @txus Finished custom Handlers support :)
authored
176 #
177 def handle(method, args, retval, object)
178 # Do what you want with these!
179 end
180
181 end
182 end
183
184 Try to think of creative uses of hijacker, write your own handlers and send
185 them to me ZOMG I CAN HAZ MOAR HENDLARZ
186
e8bd2c3 @txus first commit
authored
187 ##Note on Patches/Pull Requests
188
189 * Fork the project.
190 * Make your feature addition or bug fix.
191 * Add specs for it. This is important so I don't break it in a
192 future version unintentionally.
193 * Commit, do not mess with rakefile, version, or history.
194 If you want to have your own version, that is fine but bump version
195 in a commit by itself I can ignore when I pull.
196 * Send me a pull request. Bonus points for topic branches.
197
198 ## Copyright
199
200 Copyright (c) 2010 Josep M. Bach. See LICENSE for details.
Something went wrong with that request. Please try again.