hooked 0.0.1 → 0.1.0

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.
data/Gemfile CHANGED
@@ -2,6 +2,4 @@ source "http://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
- group :development do
6
- gem "awesome_print"
7
- end
5
+ gem "awesome_print"
data/README.md CHANGED
@@ -1,12 +1,181 @@
1
- Ruby library for Aspect Oriented Programming
1
+ Ruby Library For Aspect Oriented Programming
2
2
  ============================================
3
3
 
4
- hooked makes AOP a breeze. It lets you define and invoke code that other
5
- gems or parts of your application can hook onto. Supported hooks are before,
6
- after and around.
4
+ Hooked makes AOP a breeze. It lets you define and invoke code that gems or other
5
+ parts of your application can hook onto.
7
6
 
8
- To Do
9
- -----
7
+ Getting Started
8
+ ---------------
10
9
 
11
- * Skip hooks
12
- * Control flow (return, next, break)
10
+ require "hooked"
11
+
12
+ class User
13
+ include Hooked::Container
14
+
15
+ def save
16
+ hookable(:save_user, self)
17
+ end
18
+
19
+ hookable :save_user do |ctx|
20
+ ctx.return(Database.save(ctx.args))
21
+ end
22
+ end
23
+
24
+ class PermissionCheck
25
+ include Hooked::Container
26
+
27
+ def has_permissions?
28
+ false
29
+ end
30
+
31
+ before :save_user, :check_permissions do |ctx|
32
+ ctx.break unless has_permissions?
33
+ end
34
+ end
35
+
36
+ user = User.new
37
+ hooking = Hooked::Controller.new(user, PermissionCheck.new)
38
+ user.save # => false
39
+
40
+ Defining Hookable Code
41
+ ----------------------
42
+
43
+ To be able to define hookable code (as well as hooks) you need to mixin the
44
+ Hooked::Container module. Afterwards you can use the `::hookable` method which
45
+ takes a symbol as the hookable's name as well as a block.
46
+
47
+ class Something
48
+ include Hooked::Container
49
+
50
+ hookable :breakfast do |ctx|
51
+ puts "I'm having breakfast"
52
+ end
53
+ end
54
+
55
+ The hookable will always be executed in the context of its container's object.
56
+
57
+ Defining Hooks
58
+ --------------
59
+
60
+ For defining hooks you can use the methods `::before`, `::after` and
61
+ `::around`. They are shortcuts to `::hook` and take the arguments
62
+ `hookable_name` (name of the hookable you want to hook onto), `hook_name` and
63
+ an optional hash of before/after options.
64
+
65
+ before :breakfast, :get_up do |ctx|
66
+ puts "I'm getting out of the bed"
67
+ end
68
+
69
+ before :breakfast, :make_coffee, :after => :get_up do |ctx|
70
+ puts "I'm making coffee"
71
+ end
72
+
73
+ `:before` and `:after` can be a single hook name, an array of hook names or
74
+ `:all`. More documentation on before/after relations and how they are being
75
+ resolved can be found in the
76
+ [depression gem](http://rubygems.org/gems/depression).
77
+
78
+ Hooks will always be executed in the context of their container's object (just
79
+ as hookables).
80
+
81
+ **Note:** Hooked will at no point guarantee that hooks will be executed in the
82
+ order of definition. If you rely on execution order, you should use the
83
+ `:before` and `:after` options.
84
+
85
+ Hooking Controller
86
+ ------------------
87
+
88
+ The controller is responsible for bringing hooks into the desired order and
89
+ executing them correctly.
90
+
91
+ hooking = Hooked::Controller.new(container1, container2)
92
+ result = hooking.invoke(:my_hookable, arguments)
93
+
94
+ Arguments And Return Values
95
+ ---------------------------
96
+
97
+ All argument and return value stuff (and control flow) is managed through a
98
+ context object that is being passed between the hooks as well as the hookable.
99
+ You can pass in and out whatever you want.
100
+
101
+ after(:lowercase, :confuse_programmer) do |ctx|
102
+ ctx.result = ctx.args.map {|s| s.upper }
103
+ end
104
+
105
+ res = hooking.invoke(:lowercase, ["asdf", :foo, 123]) do |ctx|
106
+ ctx.result = ctx.args.map {|s| s.to_s.lower }
107
+ end
108
+
109
+ p res # => ["ASDF", "FOO", "123"]
110
+
111
+ Control Flow
112
+ ------------
113
+
114
+ If you want to cancel the execution of a hook and immediately start with the
115
+ next one, use `Context#next`. You would probably want to set a return value
116
+ first with `Context#result=`. `Context#return` basically does the same thing,
117
+ but additionally it always sets the return value to whatever you pass as an
118
+ argument.
119
+
120
+ # this
121
+ ctx.return "asd"
122
+ # is equal to
123
+ ctx.result = "asd"
124
+ ctx.next
125
+
126
+ # and this will result in ctx.result being nil after returning
127
+ ctx.result = 123
128
+ ctx.return
129
+
130
+ If you want to cancel the whole invocation you can use `Context#break`. This
131
+ will immediately return to where `Controller#invoke` was called. So if you call
132
+ it before the hookable was executed, it won't be executed at all.
133
+
134
+ hookable :foo do |ctx|
135
+ puts "You won't see me :/"
136
+ end
137
+
138
+ before :foo, :break_the_chain do |ctx|
139
+ ctx.break
140
+ end
141
+
142
+ You can pass a Fixnum to `Context#next` and `Context#break` to specify the
143
+ stack depth you want to jump. If you jump to high (e.g. you're hooking two
144
+ invocations deep but do `ctx.break 3`) a `NameError: uncaught throw 'hooked'`
145
+ will be raised.
146
+
147
+ **NOTE** You should definitely _not_ use Ruby's control flow constructs, they
148
+ may cause serious trouble that can be hard to debug. This may change in future
149
+ versions of Hooked. (I appreciate Pull Requests! :>)
150
+
151
+ Dependencies
152
+ ------------
153
+
154
+ * [depression](https://rubygems.org/gems/depression)
155
+ * Ruby 1.9.2
156
+ * Possibly other versions and platforms, I didn't test any yet.
157
+ * [mocha](https://rubygems.org/gems/mocha) and
158
+ [test-unit](https://rubygems.org/gems/test-unit) for development
159
+
160
+ To do & Ideas
161
+ -------------
162
+
163
+ * Skipping hooks
164
+ * Visualization of hook flow
165
+ * Make backtraces more readable
166
+ * Make Ruby's control flow constructs work for hooks
167
+
168
+ Contributing
169
+ ------------
170
+
171
+ 1. Fork at [github.com/lgierth/hooked](https://github.com/lgierth/hooked)
172
+ 2. Create a new branch
173
+ 3. Commit, commit, commit!
174
+ 4. Open a Pull Request
175
+
176
+ You can also open an issue for discussion first, if you like.
177
+
178
+ License
179
+ -------
180
+
181
+ Hooked is subject to an MIT-style license that can be found in the LICENSE file.
data/hooked.gemspec CHANGED
@@ -10,10 +10,10 @@ Gem::Specification.new do |s|
10
10
  s.authors = ["Lars Gierth"]
11
11
  s.email = ["lars.gierth@gmail.com"]
12
12
  s.homepage = "http://rubygems.org/gems/hooked"
13
- s.summary = %q{Ruby library for Aspect Oriented Programming}
14
- s.description = %q{hooked makes AOP a breeze. It lets you define and invoke
15
- code that other gems or parts of your application can hook
16
- onto. Supported hooks are before, after and around.}
13
+ s.summary = %q{Ruby Library For Aspect Oriented Programming}
14
+ s.description = %q{Hooked makes AOP a breeze. It lets you define and invoke
15
+ code that gems or other parts of your application can hook
16
+ onto.}
17
17
 
18
18
  s.add_dependency "depression"
19
19
 
@@ -0,0 +1,39 @@
1
+ module Hooked
2
+ class Context
3
+ attr_reader :args
4
+ attr_accessor :result
5
+
6
+ def initialize(args)
7
+ @args = args
8
+ end
9
+
10
+ def next(depth = 1)
11
+ return if depth < 1
12
+ throw(:hooked, {
13
+ :type => :next,
14
+ :depth => depth
15
+ })
16
+ end
17
+
18
+ def return(result)
19
+ @result = result
20
+ self.next
21
+ end
22
+
23
+ def break(depth = 1)
24
+ return if depth < 1
25
+ throw(:hooked, {
26
+ :type => :break,
27
+ :depth => depth
28
+ })
29
+ end
30
+
31
+ def skip(*hooks)
32
+ raise "Not yet implemented."
33
+ end
34
+
35
+ def skip_other(hookable, *hooks)
36
+ raise "Not yet implemented."
37
+ end
38
+ end
39
+ end
@@ -2,11 +2,9 @@ module Hooked
2
2
  Result = Struct.new(:type, :value)
3
3
 
4
4
  class Controller
5
- attr_reader :name, :containers, :hookables, :hooks
5
+ attr_reader :containers, :hookables, :hooks
6
6
 
7
- def initialize(name, *containers)
8
- @name = name
9
-
7
+ def initialize(*containers)
10
8
  @containers = []
11
9
  @hookables = {}
12
10
  @hooks = {}
@@ -18,6 +16,7 @@ module Hooked
18
16
  def add(*containers)
19
17
  @containers.push(*containers)
20
18
  containers.each do |c|
19
+ c.hooked = self
21
20
  c.class.hookables.each do |hkbl|
22
21
  hkbl.container = c
23
22
  hookables[hkbl.name] = hkbl
@@ -34,59 +33,48 @@ module Hooked
34
33
  hooks.each {|hkbl_name, hs| hooks[hkbl_name] = Depression.process(hs) }
35
34
  end
36
35
 
37
- def invoke(name, *args, &block)
36
+ def invoke(name, args = nil, &block)
38
37
  if block
39
38
  hookable = Hookable.new(name, &block)
40
39
  else
41
40
  hookable = hookables[name] || raise("Unknown hookable: #{name}")
42
41
  end
43
42
 
44
- result = catch(:hooked) do
45
- (hooks[name] || []).reverse.inject(hookable) do |next_item, item|
46
- proc {|a| call_hook(item, next_item, a) }
47
- end.call(args)
43
+ context = Context.new(args)
44
+ chain = (hooks[name] || []).reverse.inject(hookable) do |next_item, item|
45
+ proc {|ctx| call_hook(item, next_item, ctx) }
48
46
  end
49
- if (result[0] rescue nil) == :hooked_abort_chain
50
- result[1]
51
- else
52
- result
47
+
48
+ ctrl = catch(:hooked) { chain.call(context); nil }
49
+
50
+ if ctrl.respond_to?(:[])
51
+ ctrl[:depth] -= 1
52
+ throw(:hooked, ctrl) if ctrl[:depth] > 0
53
53
  end
54
+
55
+ context.result
54
56
  end
55
57
 
56
- protected
57
-
58
- # def call_wrapped_hook(hook, hookable, args)
59
- # ret = nil
60
- #
61
- # j = (0..1).each do |i|
62
- # ret = call_hook(hook, hookable, args) if i == 0
63
- # end
64
- # unless j
65
- # throw(:hooked, :hooked_abort_chain)
66
- # end
67
- #
68
- # ret
69
- # end
70
-
71
- def call_hook(hook, hookable, args)
72
- args = hook.call(*args) if hook.before?
58
+ def call_hook(hook, hookable, context)
59
+ wrap { hook.call(context) } if hook.before?
73
60
 
74
- result = catch(:hooked) do
61
+ wrap do
75
62
  if hook.around?
76
- hook.call(hookable, *args)
63
+ hook.call(context, hookable)
77
64
  else
78
- hookable.call(*args)
65
+ hookable.call(context)
79
66
  end
80
67
  end
81
- if result == :hooked_abort_chain
82
- throw(:hooked, [:hooked_abort_chain, args])
83
- else
84
- args = result
85
- end
86
-
87
- args = hook.call(*args) if hook.after?
88
68
 
89
- args
69
+ wrap { hook.call(context) } if hook.after?
70
+ end
71
+
72
+ def wrap(&block)
73
+ ctrl = catch(:hooked) { block.call; nil }
74
+ if ctrl.respond_to?(:[]) && (
75
+ ctrl[:type] == :break || ctrl[:depth] > 1)
76
+ throw(:hooked, ctrl)
77
+ end
90
78
  end
91
79
  end
92
80
  end
data/lib/hooked/hook.rb CHANGED
@@ -13,9 +13,9 @@ module Hooked
13
13
  @container, @block = container, block
14
14
  end
15
15
 
16
- def call(*args)
16
+ def call(context)
17
17
  raise RuntimeError, "No container set for hook `#{name}'" unless container
18
- container.instance_exec(*args, &@block)
18
+ container.instance_exec(context, &@block)
19
19
  end
20
20
 
21
21
  def before?
@@ -9,11 +9,11 @@ module Hooked
9
9
  @name, @container, @block = name.to_sym, container, block
10
10
  end
11
11
 
12
- def call(*args)
12
+ def call(context)
13
13
  if container
14
- container.instance_exec(*args, &@block)
14
+ container.instance_exec(context, &@block)
15
15
  else
16
- @block.call(*args)
16
+ @block.call(context)
17
17
  end
18
18
  end
19
19
  end
@@ -1,3 +1,3 @@
1
1
  module Hooked
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/hooked.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "depression"
2
2
 
3
3
  require "hooked/container"
4
+ require "hooked/context"
4
5
  require "hooked/controller"
5
6
  require "hooked/hook"
6
7
  require "hooked/hookable"
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__)) + "/helper.rb"
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class ContainerTest < Test::Unit::TestCase
4
4
  def setup
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__)) + "/helper.rb"
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class ControllerTest < Test::Unit::TestCase
4
4
  def setup
@@ -20,15 +20,8 @@ class ControllerTest < Test::Unit::TestCase
20
20
  ].map {|c| c.new }
21
21
  end
22
22
 
23
- def test_has_a_name
24
- name = :foo
25
- controller = Hooked::Controller.new(name)
26
-
27
- assert_equal name, controller.name
28
- end
29
-
30
23
  def test_has_containers
31
- controller = Hooked::Controller.new(:foo, @containers[0])
24
+ controller = Hooked::Controller.new(@containers[0])
32
25
  controller.add(*@containers[1..2])
33
26
 
34
27
  assert_equal @containers, controller.containers
@@ -40,7 +33,7 @@ class ControllerTest < Test::Unit::TestCase
40
33
  @containers[0].class.hooks[:foo][0],
41
34
  @containers[1].class.hooks[:foo][0]
42
35
  ]
43
- controller = Hooked::Controller.new(:baz, *@containers)
36
+ controller = Hooked::Controller.new(*@containers)
44
37
 
45
38
  assert_equal hookable, controller.hookables[hookable.name]
46
39
  assert_equal hooks, controller.hooks[:foo]
@@ -57,10 +50,10 @@ class ControllerTest < Test::Unit::TestCase
57
50
  end
58
51
  order = [:do_laundry, :do_something_more, :do_something_else, :do_something, :do_dishes]
59
52
 
60
- controller = Hooked::Controller.new(:baz, container.new)
53
+ controller = Hooked::Controller.new(container.new)
61
54
  assert_equal order, controller.hooks[:foo].map {|h| h.name }
62
55
 
63
- controller = Hooked::Controller.new(:baz)
56
+ controller = Hooked::Controller.new
64
57
  controller.add(container.new)
65
58
  assert_not_equal order, controller.hooks[:foo].map {|h| h.name }
66
59
 
@@ -70,11 +63,18 @@ class ControllerTest < Test::Unit::TestCase
70
63
  end
71
64
 
72
65
  def test_sets_the_container_on_hookables_and_hooks
73
- controller = Hooked::Controller.new(:foo, *@containers[1..2])
66
+ controller = Hooked::Controller.new(*@containers[1..2])
74
67
  assert_equal @containers[1], controller.hooks[:foo][0].container
75
68
  assert_equal @containers[2], controller.hookables[:foo].container
76
69
  end
77
70
 
71
+ def test_containers_are_aware_of_their_controller
72
+ controller = Hooked::Controller.new(*@containers)
73
+ @containers.each do |c|
74
+ assert_equal controller, c.hooked
75
+ end
76
+ end
77
+
78
78
  def test_invokes_hooks_in_their_containers_scope
79
79
  scope = nil
80
80
  container = Class.new do
@@ -83,7 +83,7 @@ class ControllerTest < Test::Unit::TestCase
83
83
  before(:something, :do_something_else) { scope = self }
84
84
  end.new
85
85
 
86
- controller = Hooked::Controller.new(:foo, container)
86
+ controller = Hooked::Controller.new(container)
87
87
  controller.invoke(:something)
88
88
 
89
89
  assert_equal(container, scope)
@@ -96,14 +96,14 @@ class ControllerTest < Test::Unit::TestCase
96
96
  hookable(:something) { scope = self }
97
97
  end.new
98
98
 
99
- controller = Hooked::Controller.new(:foo, container)
99
+ controller = Hooked::Controller.new(container)
100
100
  controller.invoke(:something)
101
101
 
102
102
  assert_equal(container, scope)
103
103
  end
104
104
 
105
105
  def test_invokes_dynamic_hookables_in_their_original_scope
106
- controller = Hooked::Controller.new(:foo)
106
+ controller = Hooked::Controller.new
107
107
 
108
108
  scope = nil
109
109
  controller.invoke(:something) { scope = self }
@@ -111,66 +111,124 @@ class ControllerTest < Test::Unit::TestCase
111
111
  assert_equal(self, scope)
112
112
  end
113
113
 
114
- def test_hookables_and_hooks_can_use_next
115
- pend
114
+ def test_passes_arguments_into_the_context
115
+ input = "asd"
116
+ args = []
116
117
 
117
- called = []
118
118
  container = Class.new do
119
119
  include(Hooked::Container)
120
- hookable(:something) { called << :something }
121
- before(:something, :do_something_more) { called << :do_something_more }
122
- before(:something, :do_something_else) { next; called << :do_something_else }
120
+ before(:something, :do_something_else) {|ctx| args << ctx.args}
121
+ hookable(:something) {|ctx| args << ctx.args }
123
122
  end
123
+
124
+ controller = Hooked::Controller.new(container.new)
125
+ controller.invoke(:something, input)
124
126
 
125
- controller = Hooked::Controller.new(:foo, container.new)
126
- controller.invoke(:something)
127
- assert_equal [:do_something_more, :something], called
127
+ assert_equal [input.object_id, input.object_id], args.map {|a| a.object_id }
128
128
  end
129
129
 
130
- def test_hookables_and_hooks_can_use_return
131
- pend
130
+ def test_returns_the_contexts_result
131
+ input = ["asd", "def"]
132
132
 
133
- called = []
134
- returned_arg = nil
135
133
  container = Class.new do
136
134
  include(Hooked::Container)
137
- hookable(:something) { called << :something }
138
- before(:something, :do_something_more) {|arg| return arg + 1; called << :do_something_more }
139
- before(:something, :do_something_else) {|arg| returned_arg = arg; return; called << :do_something_else }
135
+ hookable(:something) {|ctx| ctx.result = [input[0]] }
136
+ after(:something, :do_something_else) {|ctx| ctx.result << input[1] }
140
137
  end
141
138
 
142
- controller = Hooked::Controller.new(:foo, container.new)
143
- fail("Doesn't reach the code after controller.invoke()")
144
- controller.invoke(:something, 1)
145
- assert_equal [:do_something_more, :asd], called
146
- assert_equal 3, returned_arg
139
+ controller = Hooked::Controller.new(container.new)
140
+ result = controller.invoke(:something)
141
+
142
+ assert_equal(input.map {|i| i.object_id }, result.map {|r| r.object_id })
147
143
  end
148
144
 
149
- def test_hookables_and_hooks_can_use_break
150
- pend
145
+ def test_jumps_to_the_next_hook_or_hookable_when_it_catches_next
146
+ container = Class.new do
147
+ include(Hooked::Container)
148
+ before(:something, :asd, :before => :foo) {|ctx| ctx.result = [] }
149
+ before(:something, :foo) {|ctx| ctx.next; ctx.result << :foo }
150
+ hookable(:something) {|ctx| ctx.result << :something }
151
+ after(:something, :bar) {|ctx| ctx.result << :bar }
152
+ end
151
153
 
154
+ result = Hooked::Controller.new(container.new).invoke(:something)
155
+ assert_equal [:something, :bar], result
156
+ end
157
+
158
+ def test_next_can_jump_out_of_the_current_invocation
152
159
  called = []
160
+
161
+ container1 = Class.new do
162
+ include(Hooked::Container)
163
+ hookable(:something) do |ctx|
164
+ hookable(:something_else)
165
+ called << :something
166
+ end
167
+ after(:something, :bar) {|ctx| called << :bar }
168
+ end
169
+ container2 = Class.new do
170
+ include(Hooked::Container)
171
+ before(:something_else, :foo_else) {|ctx| called << :foo_else }
172
+ hookable(:something_else) {|ctx| ctx.next(2); called << :something_else }
173
+ end
174
+
175
+ Hooked::Controller.new(container1.new, container2.new).invoke(:something)
176
+ assert_equal [:foo_else, :bar], called
177
+ end
178
+
179
+ def test_crashes_if_next_depth_is_bigger_than_invocation_depth
153
180
  container = Class.new do
154
181
  include(Hooked::Container)
155
- hookable(:something) { called << :something }
156
- before(:something, :do_something_more) { called << :do_something_more }
157
- before(:something, :do_something_else) { called << :do_something_else; break }
182
+ hookable(:something) {|ctx| ctx.next(2) }
158
183
  end
159
184
 
160
- controller = Hooked::Controller.new(:foo, container.new)
161
- controller.invoke(:something)
162
- assert_equal [:do_something_more, :do_something_else], called
185
+ assert_throw(:hooked) do
186
+ Hooked::Controller.new(container.new).invoke(:something)
187
+ end
163
188
  end
164
189
 
165
- def test_arguments_and_return_values_are_passed_in_and_out
190
+ def test_returns_from_the_current_invocation_when_it_catches_break
166
191
  container = Class.new do
167
192
  include(Hooked::Container)
168
- hookable(:something) {|arg| arg += 1; arg }
169
- before(:something, :do_something_more) {|arg| arg += 1; [arg] }
170
- after(:something, :do_something_else) {|arg| arg += 1; arg }
193
+ before(:something, :asd, :before => :foo) {|ctx| ctx.result = [] }
194
+ before(:something, :foo) {|ctx| ctx.result << :foo; ctx.break }
195
+ hookable(:something) {|ctx| ctx.result << :something }
196
+ after(:something, :bar) {|ctx| ctx.result << :bar }
197
+ end
198
+
199
+ result = Hooked::Controller.new(container.new).invoke(:something)
200
+ assert_equal [:foo], result
201
+ end
202
+
203
+ def test_break_can_jump_out_of_the_current_invocation
204
+ called = []
205
+
206
+ container1 = Class.new do
207
+ include(Hooked::Container)
208
+ hookable(:something) do |ctx|
209
+ hookable(:something_else)
210
+ called << :something
211
+ end
212
+ after(:something, :bar) {|ctx| called << :bar }
213
+ end
214
+ container2 = Class.new do
215
+ include(Hooked::Container)
216
+ before(:something_else, :foo_else) {|ctx| called << :foo_else }
217
+ hookable(:something_else) {|ctx| ctx.break(2); called << :something_else }
218
+ end
219
+
220
+ Hooked::Controller.new(container1.new, container2.new).invoke(:something)
221
+ assert_equal [:foo_else], called
222
+ end
223
+
224
+ def test_crashes_if_break_depth_is_bigger_than_invocation_depth
225
+ container = Class.new do
226
+ include(Hooked::Container)
227
+ hookable(:something) {|ctx| ctx.break(2) }
228
+ end
229
+
230
+ assert_throw(:hooked) do
231
+ Hooked::Controller.new(container.new).invoke(:something)
171
232
  end
172
-
173
- controller = Hooked::Controller.new(:foo, container.new)
174
- assert_equal 4, controller.invoke(:something, 1)
175
233
  end
176
234
  end
data/test/helper.rb CHANGED
@@ -4,6 +4,7 @@ Bundler.setup(:default, :development)
4
4
 
5
5
  require "test/unit"
6
6
  require "mocha"
7
- require "awesome_print"
7
+
8
+ require "awesome_print" rescue nil
8
9
 
9
10
  require "hooked"
data/test/hook_test.rb CHANGED
@@ -1,6 +1,10 @@
1
- require File.dirname(__FILE__) + "/helper.rb"
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class HookTest < Test::Unit::TestCase
4
+ def context
5
+ Hooked::Context
6
+ end
7
+
4
8
  def test_has_a_name
5
9
  name = :foo
6
10
  hook = Hooked::Hook.new(:before, name) {}
@@ -65,31 +69,22 @@ class HookTest < Test::Unit::TestCase
65
69
  scope = self
66
70
  end
67
71
 
68
- assert_raise(RuntimeError) { hook.call }
72
+ assert_raise(RuntimeError) { hook.call(context) }
69
73
 
70
74
  container = stub("container")
71
75
  hook.container = container
72
- hook.call
76
+ hook.call(context)
73
77
  assert_equal(container, scope)
74
78
  end
75
79
 
76
- def test_passes_arguments_to_the_block
77
- args = [123, "asd"]
78
- passed_args = nil
79
- hook = Hooked::Hook.new(:before, :foo, {}, stub("container")) do |*args|
80
- passed_args = args
81
- end
82
-
83
- hook.call(args)
84
- assert_equal(args, passed_args)
85
- end
86
-
87
- def test_passes_blocks_return_to_the_caller
88
- ret = 123
89
- hook = Hooked::Hook.new(:before, :foo, {}, stub("container")) do
90
- ret
80
+ def test_passes_context_to_the_block
81
+ ctx = context
82
+ ctx2 = nil
83
+ hook = Hooked::Hook.new(:before, :foo, {}, stub("container")) do |c|
84
+ ctx2 = c
91
85
  end
92
86
 
93
- assert_equal(ret, hook.call)
87
+ hook.call(ctx)
88
+ assert_equal(ctx, ctx2)
94
89
  end
95
90
  end
@@ -1,6 +1,10 @@
1
- require File.dirname(__FILE__) + "/helper.rb"
1
+ require File.expand_path("../helper", __FILE__)
2
2
 
3
3
  class HookableTest < Test::Unit::TestCase
4
+ def context
5
+ Hooked::Context
6
+ end
7
+
4
8
  def test_has_a_name
5
9
  name = :foo
6
10
  hookable = Hooked::Hookable.new(name) {}
@@ -35,7 +39,7 @@ class HookableTest < Test::Unit::TestCase
35
39
  scope = self
36
40
  end
37
41
 
38
- hookable.call
42
+ hookable.call(context)
39
43
  assert_equal container, scope
40
44
  end
41
45
 
@@ -45,27 +49,18 @@ class HookableTest < Test::Unit::TestCase
45
49
  scope = self
46
50
  end
47
51
 
48
- hookable.call
52
+ hookable.call(context)
49
53
  assert_equal self, scope
50
54
  end
51
55
 
52
- def test_passes_arguments_to_the_block
53
- args = [123, "asd"]
54
- passed_args = nil
55
- hookable = Hooked::Hookable.new(:foo) do |*args|
56
- passed_args = args
57
- end
58
-
59
- hookable.call(args)
60
- assert_equal(args, passed_args)
61
- end
62
-
63
- def test_passes_block_return_to_the_caller
64
- ret = 123
65
- hookable = Hooked::Hookable.new(:foo) do
66
- ret
56
+ def test_passes_context_to_the_block
57
+ ctx = context
58
+ ctx2 = nil
59
+ hookable = Hooked::Hookable.new(:foo) do |c|
60
+ ctx2 = c
67
61
  end
68
62
 
69
- assert_equal(ret, hookable.call)
63
+ hookable.call(ctx)
64
+ assert_equal(ctx, ctx2)
70
65
  end
71
66
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hooked
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 0
9
7
  - 1
10
- version: 0.0.1
8
+ - 0
9
+ version: 0.1.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Lars Gierth
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-11-25 00:00:00 +01:00
17
+ date: 2010-12-20 00:00:00 +01:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -26,7 +25,6 @@ dependencies:
26
25
  requirements:
27
26
  - - ">="
28
27
  - !ruby/object:Gem::Version
29
- hash: 3
30
28
  segments:
31
29
  - 0
32
30
  version: "0"
@@ -40,7 +38,6 @@ dependencies:
40
38
  requirements:
41
39
  - - ">="
42
40
  - !ruby/object:Gem::Version
43
- hash: 3
44
41
  segments:
45
42
  - 0
46
43
  version: "0"
@@ -54,16 +51,15 @@ dependencies:
54
51
  requirements:
55
52
  - - ">="
56
53
  - !ruby/object:Gem::Version
57
- hash: 3
58
54
  segments:
59
55
  - 0
60
56
  version: "0"
61
57
  type: :development
62
58
  version_requirements: *id003
63
59
  description: |-
64
- hooked makes AOP a breeze. It lets you define and invoke
65
- code that other gems or parts of your application can hook
66
- onto. Supported hooks are before, after and around.
60
+ Hooked makes AOP a breeze. It lets you define and invoke
61
+ code that gems or other parts of your application can hook
62
+ onto.
67
63
  email:
68
64
  - lars.gierth@gmail.com
69
65
  executables: []
@@ -80,6 +76,7 @@ files:
80
76
  - hooked.gemspec
81
77
  - lib/hooked.rb
82
78
  - lib/hooked/container.rb
79
+ - lib/hooked/context.rb
83
80
  - lib/hooked/controller.rb
84
81
  - lib/hooked/hook.rb
85
82
  - lib/hooked/hookable.rb
@@ -103,7 +100,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
100
  requirements:
104
101
  - - ">="
105
102
  - !ruby/object:Gem::Version
106
- hash: 3
107
103
  segments:
108
104
  - 0
109
105
  version: "0"
@@ -112,7 +108,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
108
  requirements:
113
109
  - - ">="
114
110
  - !ruby/object:Gem::Version
115
- hash: 3
116
111
  segments:
117
112
  - 0
118
113
  version: "0"
@@ -122,6 +117,6 @@ rubyforge_project:
122
117
  rubygems_version: 1.3.7
123
118
  signing_key:
124
119
  specification_version: 3
125
- summary: Ruby library for Aspect Oriented Programming
120
+ summary: Ruby Library For Aspect Oriented Programming
126
121
  test_files: []
127
122