hooked 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "awesome_print"
7
+ end
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Lars Gierth
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ Ruby library for Aspect Oriented Programming
2
+ ============================================
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.
7
+
8
+ To Do
9
+ -----
10
+
11
+ * Skip hooks
12
+ * Control flow (return, next, break)
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ task :default => :test
5
+
6
+ require "rake/testtask"
7
+ Rake::TestTask.new do |t|
8
+ t.libs = ["lib"]
9
+ t.test_files = FileList["test/*_test.rb"]
10
+ end
data/hooked.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "hooked/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "hooked"
7
+ s.version = Hooked::VERSION
8
+ s.date = Date.today.to_s
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Lars Gierth"]
11
+ s.email = ["lars.gierth@gmail.com"]
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.}
17
+
18
+ s.add_dependency "depression"
19
+
20
+ s.add_development_dependency "test-unit"
21
+ s.add_development_dependency "mocha"
22
+
23
+ s.files = `git ls-files`.split("\n") - [".gitignore", ".rvmrc"]
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = ["lib"]
27
+ end
data/lib/hooked.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "depression"
2
+
3
+ require "hooked/container"
4
+ require "hooked/controller"
5
+ require "hooked/hook"
6
+ require "hooked/hookable"
@@ -0,0 +1,52 @@
1
+ module Hooked
2
+ module Container
3
+ attr_accessor :hooked
4
+
5
+ def hookable(name, *args, &block)
6
+ hooked.invoke(name, *args, &block)
7
+ end
8
+
9
+ module ClassMethods
10
+ attr_reader :hookables, :hooks
11
+
12
+ def hookable(name, &block)
13
+ @hookables << Hookable.new(name, &block)
14
+ end
15
+
16
+ def hook(type, hookable, name, opts = {}, &block)
17
+ opts[:before] ||= []
18
+ unless opts[:before].respond_to?(:each) or opts[:before] == :all
19
+ opts[:before] = [opts[:before]]
20
+ end
21
+
22
+ opts[:after] ||= []
23
+ unless opts[:after].respond_to?(:each) or opts[:after] == :all
24
+ opts[:after] = [opts[:after]]
25
+ end
26
+
27
+ @hooks[hookable] ||= []
28
+ @hooks[hookable] << Hook.new(type, name, opts, &block)
29
+ end
30
+
31
+ def before(*args, &block)
32
+ hook(:before, *args, &block)
33
+ end
34
+
35
+ def around(*args, &block)
36
+ hook(:around, *args, &block)
37
+ end
38
+
39
+ def after(*args, &block)
40
+ hook(:after, *args, &block)
41
+ end
42
+ end
43
+
44
+ def self.included(klass)
45
+ klass.class_eval do
46
+ extend(ClassMethods)
47
+ @hookables = []
48
+ @hooks = {}
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,92 @@
1
+ module Hooked
2
+ Result = Struct.new(:type, :value)
3
+
4
+ class Controller
5
+ attr_reader :name, :containers, :hookables, :hooks
6
+
7
+ def initialize(name, *containers)
8
+ @name = name
9
+
10
+ @containers = []
11
+ @hookables = {}
12
+ @hooks = {}
13
+
14
+ add(*containers)
15
+ refresh
16
+ end
17
+
18
+ def add(*containers)
19
+ @containers.push(*containers)
20
+ containers.each do |c|
21
+ c.class.hookables.each do |hkbl|
22
+ hkbl.container = c
23
+ hookables[hkbl.name] = hkbl
24
+ end
25
+ c.class.hooks.each do |hkbl_name, hs|
26
+ hs.each {|h| h.container = c }
27
+ @hooks[hkbl_name] ||= []
28
+ @hooks[hkbl_name].push(*hs)
29
+ end
30
+ end
31
+ end
32
+
33
+ def refresh
34
+ hooks.each {|hkbl_name, hs| hooks[hkbl_name] = Depression.process(hs) }
35
+ end
36
+
37
+ def invoke(name, *args, &block)
38
+ if block
39
+ hookable = Hookable.new(name, &block)
40
+ else
41
+ hookable = hookables[name] || raise("Unknown hookable: #{name}")
42
+ end
43
+
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)
48
+ end
49
+ if (result[0] rescue nil) == :hooked_abort_chain
50
+ result[1]
51
+ else
52
+ result
53
+ end
54
+ end
55
+
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?
73
+
74
+ result = catch(:hooked) do
75
+ if hook.around?
76
+ hook.call(hookable, *args)
77
+ else
78
+ hookable.call(*args)
79
+ end
80
+ 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
+
89
+ args
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,33 @@
1
+ module Hooked
2
+ class Hook
3
+ attr_reader :type, :name, :relations
4
+ attr_accessor :container, :weight
5
+
6
+ def initialize(type, name, relations = {}, container = nil, &block)
7
+ raise ArgumentError, "Invalid hook type `#{type}'" unless [
8
+ :before, :after, :around
9
+ ].include?(type.to_sym)
10
+ @type, @name, @relations = type.to_sym, name.to_sym, relations
11
+
12
+ raise ArgumentError, "Hooked::Hookable.new expects a block." unless block
13
+ @container, @block = container, block
14
+ end
15
+
16
+ def call(*args)
17
+ raise RuntimeError, "No container set for hook `#{name}'" unless container
18
+ container.instance_exec(*args, &@block)
19
+ end
20
+
21
+ def before?
22
+ type == :before
23
+ end
24
+
25
+ def after?
26
+ type == :after
27
+ end
28
+
29
+ def around?
30
+ type == :around
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ module Hooked
2
+ class Hookable
3
+ attr_reader :name
4
+ attr_accessor :container
5
+
6
+ def initialize(name, container = nil, &block)
7
+ raise ArgumentError, "Hooked::Hookable.new expects a block." unless block
8
+
9
+ @name, @container, @block = name.to_sym, container, block
10
+ end
11
+
12
+ def call(*args)
13
+ if container
14
+ container.instance_exec(*args, &@block)
15
+ else
16
+ @block.call(*args)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Hooked
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,71 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + "/helper.rb"
2
+
3
+ class ContainerTest < Test::Unit::TestCase
4
+ def setup
5
+ @container = Class.new { include(Hooked::Container) }
6
+ end
7
+
8
+ def teardown
9
+ Mocha::Mockery.instance.teardown
10
+ end
11
+
12
+ def test_has_hookables
13
+ block = proc {}
14
+ @container.hookable(:foo, &block)
15
+
16
+ assert_equal :foo, @container.hookables[0].name
17
+ assert @container.hookables[0].respond_to?(:call)
18
+ end
19
+
20
+ def test_has_a_shorthand_method_for_invoking_hookables
21
+ container = @container.new
22
+ container.hooked = stub("controller") do
23
+ expects(:invoke).once.with(:foo, 123).returns("asdf")
24
+ end
25
+
26
+ assert_equal "asdf", container.hookable(:foo, 123)
27
+ end
28
+
29
+ def test_has_hooks
30
+ block = proc {}
31
+ @container.hook(:after, :work, :start_revolution, {
32
+ :before => :utopia
33
+ }, &block)
34
+ @container.hook(:around, :foo, :do_something, {
35
+ :before => :all,
36
+ :after => [:do_something_else, :snooze]
37
+ }, &block)
38
+
39
+ h = @container.hooks[:work][0]
40
+ assert_equal :after, h.type
41
+ assert_equal :start_revolution, h.name
42
+ assert_equal({
43
+ :before => [:utopia],
44
+ :after => []
45
+ }, h.relations)
46
+ assert h.respond_to?(:call)
47
+ assert h.respond_to?(:container=)
48
+
49
+ h = @container.hooks[:foo][0]
50
+ assert_equal :around, h.type
51
+ assert_equal :do_something, h.name
52
+ assert_equal({
53
+ :before => :all,
54
+ :after => [:do_something_else, :snooze]
55
+ }, h.relations)
56
+ end
57
+
58
+ def test_has_shorthand_methods_for_before_around_and_after
59
+ args = [:foo, :bar, {:before => :all}]
60
+ block = proc {}
61
+
62
+ @container.expects(:hook).once.with(:before, *args)
63
+ @container.before(*args, &block)
64
+
65
+ @container.expects(:hook).once.with(:around, *args)
66
+ @container.around(*args, &block)
67
+
68
+ @container.expects(:hook).once.with(:after, *args)
69
+ @container.after(*args, &block)
70
+ end
71
+ end
@@ -0,0 +1,176 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + "/helper.rb"
2
+
3
+ class ControllerTest < Test::Unit::TestCase
4
+ def setup
5
+ @containers = [
6
+ Class.new do
7
+ include Hooked::Container
8
+ before :foo, :do_something do |*args|; end
9
+ end,
10
+ Class.new do
11
+ include Hooked::Container
12
+ around :foo, :do_something_else do |h, *args|
13
+ h.call(*args)
14
+ end
15
+ end,
16
+ Class.new do
17
+ include Hooked::Container
18
+ hookable :foo do |*args|; end
19
+ end
20
+ ].map {|c| c.new }
21
+ end
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
+ def test_has_containers
31
+ controller = Hooked::Controller.new(:foo, @containers[0])
32
+ controller.add(*@containers[1..2])
33
+
34
+ assert_equal @containers, controller.containers
35
+ end
36
+
37
+ def test_collects_hookables_and_hooks_from_containers
38
+ hookable = @containers[2].class.hookables[0]
39
+ hooks = [
40
+ @containers[0].class.hooks[:foo][0],
41
+ @containers[1].class.hooks[:foo][0]
42
+ ]
43
+ controller = Hooked::Controller.new(:baz, *@containers)
44
+
45
+ assert_equal hookable, controller.hookables[hookable.name]
46
+ assert_equal hooks, controller.hooks[:foo]
47
+ end
48
+
49
+ def test_sorts_hooks
50
+ container = Class.new do
51
+ include(Hooked::Container)
52
+ before(:foo, :do_something) {}
53
+ before(:foo, :do_dishes, :after => :all) {}
54
+ around(:foo, :do_something_more, :before => :do_something) {}
55
+ after(:foo, :do_something_else, :after => :do_something_more, :before => :do_something) {}
56
+ around(:foo, :do_laundry, :before => :all) {}
57
+ end
58
+ order = [:do_laundry, :do_something_more, :do_something_else, :do_something, :do_dishes]
59
+
60
+ controller = Hooked::Controller.new(:baz, container.new)
61
+ assert_equal order, controller.hooks[:foo].map {|h| h.name }
62
+
63
+ controller = Hooked::Controller.new(:baz)
64
+ controller.add(container.new)
65
+ assert_not_equal order, controller.hooks[:foo].map {|h| h.name }
66
+
67
+ controller.hooks[:foo].shuffle!
68
+ controller.refresh
69
+ assert_equal order, controller.hooks[:foo].map {|h| h.name }
70
+ end
71
+
72
+ def test_sets_the_container_on_hookables_and_hooks
73
+ controller = Hooked::Controller.new(:foo, *@containers[1..2])
74
+ assert_equal @containers[1], controller.hooks[:foo][0].container
75
+ assert_equal @containers[2], controller.hookables[:foo].container
76
+ end
77
+
78
+ def test_invokes_hooks_in_their_containers_scope
79
+ scope = nil
80
+ container = Class.new do
81
+ include(Hooked::Container)
82
+ hookable(:something) {}
83
+ before(:something, :do_something_else) { scope = self }
84
+ end.new
85
+
86
+ controller = Hooked::Controller.new(:foo, container)
87
+ controller.invoke(:something)
88
+
89
+ assert_equal(container, scope)
90
+ end
91
+
92
+ def test_invokes_hookables_in_their_containers_scope
93
+ scope = nil
94
+ container = Class.new do
95
+ include(Hooked::Container)
96
+ hookable(:something) { scope = self }
97
+ end.new
98
+
99
+ controller = Hooked::Controller.new(:foo, container)
100
+ controller.invoke(:something)
101
+
102
+ assert_equal(container, scope)
103
+ end
104
+
105
+ def test_invokes_dynamic_hookables_in_their_original_scope
106
+ controller = Hooked::Controller.new(:foo)
107
+
108
+ scope = nil
109
+ controller.invoke(:something) { scope = self }
110
+
111
+ assert_equal(self, scope)
112
+ end
113
+
114
+ def test_hookables_and_hooks_can_use_next
115
+ pend
116
+
117
+ called = []
118
+ container = Class.new do
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 }
123
+ end
124
+
125
+ controller = Hooked::Controller.new(:foo, container.new)
126
+ controller.invoke(:something)
127
+ assert_equal [:do_something_more, :something], called
128
+ end
129
+
130
+ def test_hookables_and_hooks_can_use_return
131
+ pend
132
+
133
+ called = []
134
+ returned_arg = nil
135
+ container = Class.new do
136
+ 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 }
140
+ end
141
+
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
147
+ end
148
+
149
+ def test_hookables_and_hooks_can_use_break
150
+ pend
151
+
152
+ called = []
153
+ container = Class.new do
154
+ 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 }
158
+ end
159
+
160
+ controller = Hooked::Controller.new(:foo, container.new)
161
+ controller.invoke(:something)
162
+ assert_equal [:do_something_more, :do_something_else], called
163
+ end
164
+
165
+ def test_arguments_and_return_values_are_passed_in_and_out
166
+ container = Class.new do
167
+ 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 }
171
+ end
172
+
173
+ controller = Hooked::Controller.new(:foo, container.new)
174
+ assert_equal 4, controller.invoke(:something, 1)
175
+ end
176
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ Bundler.setup(:default, :development)
4
+
5
+ require "test/unit"
6
+ require "mocha"
7
+ require "awesome_print"
8
+
9
+ require "hooked"
data/test/hook_test.rb ADDED
@@ -0,0 +1,95 @@
1
+ require File.dirname(__FILE__) + "/helper.rb"
2
+
3
+ class HookTest < Test::Unit::TestCase
4
+ def test_has_a_name
5
+ name = :foo
6
+ hook = Hooked::Hook.new(:before, name) {}
7
+
8
+ assert_equal name, hook.name
9
+ end
10
+
11
+ def test_has_a_type
12
+ build_hook = proc do |type|
13
+ Hooked::Hook.new(type, :foo) {}
14
+ end
15
+
16
+ hook = build_hook.call(:before)
17
+ assert_equal :before, hook.type
18
+
19
+ assert hook.before?
20
+ assert build_hook.call(:after).after?
21
+ assert build_hook.call(:around).around?
22
+
23
+ assert_raise(ArgumentError) do
24
+ build_hook.call(:asdas)
25
+ end
26
+ end
27
+
28
+ def test_has_relations
29
+ relations = {
30
+ :before => 123
31
+ }
32
+ hook = Hooked::Hook.new(:before, :foo, relations) {}
33
+ assert_equal(123, hook.relations[:before])
34
+
35
+ hook.relations[:before] = 456
36
+ assert_equal(456, hook.relations[:before])
37
+
38
+ hook.relations[:after] = "asd"
39
+ assert_equal("asd", hook.relations[:after])
40
+ end
41
+
42
+ def test_has_a_container
43
+ container = stub("container")
44
+ hook = Hooked::Hook.new(:before, :foo, {}, container) {}
45
+ assert_equal container, hook.container
46
+
47
+ container2 = stub("container2")
48
+ hook.container = container2
49
+ assert_equal container2, hook.container
50
+ end
51
+
52
+ def test_expects_a_block
53
+ assert_nothing_raised do
54
+ Hooked::Hook.new(:before, :foo) {}
55
+ end
56
+
57
+ assert_raise(ArgumentError) do
58
+ Hooked::Hook.new(:before, :foo)
59
+ end
60
+ end
61
+
62
+ def test_executes_block_in_the_containers_scope
63
+ scope = nil
64
+ hook = Hooked::Hook.new(:before, :foo) do
65
+ scope = self
66
+ end
67
+
68
+ assert_raise(RuntimeError) { hook.call }
69
+
70
+ container = stub("container")
71
+ hook.container = container
72
+ hook.call
73
+ assert_equal(container, scope)
74
+ end
75
+
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
91
+ end
92
+
93
+ assert_equal(ret, hook.call)
94
+ end
95
+ end
@@ -0,0 +1,71 @@
1
+ require File.dirname(__FILE__) + "/helper.rb"
2
+
3
+ class HookableTest < Test::Unit::TestCase
4
+ def test_has_a_name
5
+ name = :foo
6
+ hookable = Hooked::Hookable.new(name) {}
7
+
8
+ assert_equal name, hookable.name
9
+ end
10
+
11
+ def test_can_have_a_container
12
+ container = Object.new
13
+ hookable = Hooked::Hookable.new(:foo, container) {}
14
+
15
+ assert_equal container, hookable.container
16
+
17
+ assert_nil Hooked::Hookable.new(:foo) {}.container
18
+ end
19
+
20
+ def test_expects_a_block
21
+ assert_nothing_raised do
22
+ Hooked::Hookable.new(:foo) {}
23
+ end
24
+
25
+ assert_raise(ArgumentError) do
26
+ Hooked::Hookable.new(:foo)
27
+ end
28
+ end
29
+
30
+ def test_executes_block_in_the_containers_scope
31
+ container = Object.new
32
+
33
+ scope = nil
34
+ hookable = Hooked::Hookable.new(:foo, container) do
35
+ scope = self
36
+ end
37
+
38
+ hookable.call
39
+ assert_equal container, scope
40
+ end
41
+
42
+ def test_executes_block_in_its_original_scope_if_no_container_given
43
+ scope = nil
44
+ hookable = Hooked::Hookable.new(:foo) do
45
+ scope = self
46
+ end
47
+
48
+ hookable.call
49
+ assert_equal self, scope
50
+ end
51
+
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
67
+ end
68
+
69
+ assert_equal(ret, hookable.call)
70
+ end
71
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hooked
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Lars Gierth
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-25 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: depression
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: test-unit
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: mocha
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ type: :development
62
+ version_requirements: *id003
63
+ 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.
67
+ email:
68
+ - lars.gierth@gmail.com
69
+ executables: []
70
+
71
+ extensions: []
72
+
73
+ extra_rdoc_files: []
74
+
75
+ files:
76
+ - Gemfile
77
+ - LICENSE
78
+ - README.md
79
+ - Rakefile
80
+ - hooked.gemspec
81
+ - lib/hooked.rb
82
+ - lib/hooked/container.rb
83
+ - lib/hooked/controller.rb
84
+ - lib/hooked/hook.rb
85
+ - lib/hooked/hookable.rb
86
+ - lib/hooked/version.rb
87
+ - test/container_test.rb
88
+ - test/controller_test.rb
89
+ - test/helper.rb
90
+ - test/hook_test.rb
91
+ - test/hookable_test.rb
92
+ has_rdoc: true
93
+ homepage: http://rubygems.org/gems/hooked
94
+ licenses: []
95
+
96
+ post_install_message:
97
+ rdoc_options: []
98
+
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ requirements: []
120
+
121
+ rubyforge_project:
122
+ rubygems_version: 1.3.7
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: Ruby library for Aspect Oriented Programming
126
+ test_files: []
127
+