callbacks 0.0.2 → 0.0.3
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/History.txt +8 -0
- data/Manifest.txt +1 -0
- data/README.txt +1 -1
- data/Rakefile +3 -0
- data/Version.txt +1 -1
- data/lib/callback.rb +8 -7
- data/lib/callbacks.rb +18 -4
- data/lib/classmethods.rb +40 -15
- data/lib/instancemethods.rb +23 -31
- data/test/test_callbacks.rb +21 -25
- data/test/test_singleton_callbacks.rb +85 -0
- data/test/tester_class.rb +2 -2
- metadata +5 -3
data/History.txt
CHANGED
@@ -10,3 +10,11 @@
|
|
10
10
|
* API still not stable
|
11
11
|
* Callbacks now picks up "before#{callback}" and "after_#{callback}" instance methods automatically
|
12
12
|
* Some documentation added
|
13
|
+
|
14
|
+
== 0.0.3 / 2008-10-14
|
15
|
+
|
16
|
+
* Callbacks per object instance (singleton callbacks)
|
17
|
+
* Shuffled some code between instancemethods and classmethods
|
18
|
+
* Some more tests
|
19
|
+
* API still not stable
|
20
|
+
* Some documentation added
|
data/Manifest.txt
CHANGED
data/README.txt
CHANGED
@@ -22,7 +22,7 @@ This package makes it simple to add callbacks a.k.a. "hooks" to ruby classes
|
|
22
22
|
Object.send(:include, Callbacks)
|
23
23
|
Object.add_callback_methods :inspect
|
24
24
|
Object.before_inspect do
|
25
|
-
|
25
|
+
print "Going to inspect #{self.class}\n"
|
26
26
|
end
|
27
27
|
|
28
28
|
o = Object.new
|
data/Rakefile
CHANGED
data/Version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/lib/callback.rb
CHANGED
@@ -2,14 +2,14 @@ class Callback
|
|
2
2
|
attr_accessor :method, :input
|
3
3
|
attr_writer :proc
|
4
4
|
ACCEPTED = [Symbol, Proc, String, Method]
|
5
|
+
ACCEPTANCE_ERROR = "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method. %s is none of those."
|
5
6
|
|
6
7
|
def initialize(method, input, &block)
|
7
|
-
#self.method = method
|
8
8
|
self.input = input
|
9
9
|
self.input = block if block_given?
|
10
10
|
|
11
11
|
if not ACCEPTED.include? self.input.class
|
12
|
-
raise
|
12
|
+
raise ACCEPTANCE_ERROR % self.input.class
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -25,19 +25,20 @@ class Callback
|
|
25
25
|
case self.input
|
26
26
|
when String
|
27
27
|
Proc.new { eval(self.input) }
|
28
|
-
|
29
|
-
|
30
|
-
# end
|
28
|
+
else
|
29
|
+
nil
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
34
33
|
def generate_block
|
35
34
|
case self.input
|
36
35
|
when Symbol
|
37
|
-
|
38
|
-
Proc.new { self.send(
|
36
|
+
instance_method = self.input.to_sym
|
37
|
+
Proc.new { self.send(instance_method) }
|
39
38
|
when Proc, Method
|
40
39
|
self.input
|
40
|
+
else
|
41
|
+
nil
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
data/lib/callbacks.rb
CHANGED
@@ -1,20 +1,34 @@
|
|
1
1
|
#Idea stolen from rails/activerecord
|
2
2
|
module Callbacks
|
3
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
4
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
5
|
+
|
3
6
|
require 'observer'
|
4
|
-
require
|
7
|
+
require "#{PATH}/ext/metaid.rb"
|
5
8
|
require 'callbackchain.rb'
|
6
9
|
require 'instancemethods.rb'
|
7
10
|
require 'classmethods.rb'
|
8
11
|
require 'callback.rb'
|
9
|
-
|
12
|
+
|
10
13
|
#Sets all things right
|
11
14
|
def self.included(base) #:nodoc:
|
12
|
-
base.extend Observable #why?
|
13
15
|
base.extend Callbacks::ClassMethods
|
14
16
|
base.send(:include, Callbacks::InstanceMethods)
|
15
17
|
end
|
18
|
+
|
19
|
+
def self.version
|
20
|
+
VERSION
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.libpath( *args )
|
24
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.path( *args )
|
28
|
+
args.empty? ? PATH : ::File.join(PATH, *args)
|
29
|
+
end
|
30
|
+
|
16
31
|
end
|
17
32
|
|
18
33
|
#TODO: add aliases like add_hook(), callbacks(), et cetera
|
19
|
-
#TODO: feature to add hooks/callbacks to instances instead of only classes
|
20
34
|
#TODO: make all of the activesupport features/tests work
|
data/lib/classmethods.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Callbacks
|
2
2
|
module ClassMethods
|
3
3
|
|
4
|
-
def callback_methods
|
4
|
+
def callback_methods
|
5
5
|
#Use one @, else it gets stored in the module and then it will be avaiable in every class that uses callback
|
6
6
|
@callback_methods ||= []
|
7
7
|
end
|
@@ -30,15 +30,38 @@ module Callbacks
|
|
30
30
|
self.callback_methods.delete(method.to_sym)
|
31
31
|
end
|
32
32
|
|
33
|
+
#TODO: make this nicer
|
34
|
+
def callback_actions_for(method, type)
|
35
|
+
if self.callback_actions[method].nil?
|
36
|
+
callback_actions = []
|
37
|
+
else
|
38
|
+
callback_actions = self.callback_actions[method][type] ||= []
|
39
|
+
end
|
40
|
+
|
41
|
+
#Removed this because this didn't work
|
42
|
+
#callback_actions_for is called four times with every callback method:
|
43
|
+
# before, before metaclass, after, after metaclass
|
44
|
+
# And a class and metaclass both now the #{type}_#{method} method
|
45
|
+
# So it got called twice
|
46
|
+
# if self.instance_methods.include?("#{type}_#{method}")
|
47
|
+
# if not callback_actions.include? "#{type}_#{method}".to_sym
|
48
|
+
# callback = self.add_callback_action(type, method, "#{type}_#{method}".to_sym)
|
49
|
+
# callback_actions << callback
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
|
53
|
+
return callback_actions
|
54
|
+
end
|
55
|
+
|
33
56
|
def build_callback_methods(method)
|
34
57
|
build_before_callback_method(method)
|
35
58
|
build_after_callback_method(method)
|
36
59
|
|
37
60
|
class_eval <<-"end_eval"
|
38
61
|
def #{method}_with_callbacks
|
39
|
-
trigger_callback_actions(:#{method}, :before)
|
62
|
+
self.trigger_callback_actions(:#{method}, :before)
|
40
63
|
retval = self.send("#{method}_without_callbacks")
|
41
|
-
trigger_callback_actions(:#{method}, :after)
|
64
|
+
self.trigger_callback_actions(:#{method}, :after)
|
42
65
|
return retval
|
43
66
|
end
|
44
67
|
end_eval
|
@@ -63,26 +86,28 @@ module Callbacks
|
|
63
86
|
ca[method][type] << callback
|
64
87
|
return callback
|
65
88
|
end
|
66
|
-
|
67
|
-
private
|
89
|
+
|
68
90
|
def build_before_callback_method(method)
|
69
|
-
|
70
|
-
|
71
|
-
def before_#{method}(*callbacks, &block)
|
72
|
-
add_callback_action :before, :#{method}, *callbacks, &block
|
73
|
-
end
|
74
|
-
|
75
|
-
end_eval
|
91
|
+
build_callback_method(:before, method)
|
76
92
|
end
|
77
93
|
|
78
94
|
def build_after_callback_method(method)
|
79
|
-
|
95
|
+
build_callback_method(:after, method)
|
96
|
+
end
|
97
|
+
|
98
|
+
def build_callback_method(type, method)
|
99
|
+
method = <<-"end_eval"
|
100
|
+
|
101
|
+
# def #{type}_#{method}(*callbacks, &block)
|
102
|
+
# self.class.add_callback_action(:#{type}, :#{method}, *callbacks, &block)
|
103
|
+
# end
|
80
104
|
|
81
|
-
def
|
82
|
-
add_callback_action
|
105
|
+
def self.#{type}_#{method}(*callbacks, &block)
|
106
|
+
add_callback_action(:#{type}, :#{method}, *callbacks, &block)
|
83
107
|
end
|
84
108
|
|
85
109
|
end_eval
|
110
|
+
module_eval(method)
|
86
111
|
end
|
87
112
|
|
88
113
|
end
|
data/lib/instancemethods.rb
CHANGED
@@ -1,49 +1,41 @@
|
|
1
1
|
module Callbacks
|
2
2
|
module InstanceMethods
|
3
3
|
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
#
|
4
|
+
def trigger_callback_actions(method, type)
|
5
|
+
trigger_class_callback_actions(method, type) if self.class.respond_to?(:callback_actions_for)
|
6
|
+
trigger_metaclass_callback_actions(method, type) if self.metaclass.respond_to?(:callback_actions_for)
|
7
|
+
#Should I return something?
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
#TODO: do something with a block or proc or something :p
|
11
|
+
#Instead of self.class/self.metaclass
|
12
|
+
def trigger_class_callback_actions(method, type)
|
13
|
+
self.class.callback_actions_for(method, type).each do |callback|
|
14
|
+
|
15
|
+
if callback.block
|
16
|
+
self.instance_eval(&callback.block)
|
17
|
+
else
|
18
|
+
callback.proc.call
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
|
-
#
|
19
|
-
# add it!
|
20
|
-
#Dit kan mooier!
|
22
|
+
#I'm not happy with this...
|
21
23
|
if self.respond_to?("#{type}_#{method}")
|
22
|
-
|
23
|
-
#callback_actions << Callback.new(method, "#{type}_#{method}".to_sym)
|
24
|
-
callback = self.class.add_callback_action(type, method, "#{type}_#{method}".to_sym)
|
25
|
-
callback_actions << callback
|
26
|
-
end
|
24
|
+
self.send("#{type}_#{method}")
|
27
25
|
end
|
28
|
-
|
29
|
-
return callback_actions
|
30
26
|
end
|
31
27
|
|
32
|
-
def
|
33
|
-
self.
|
34
|
-
|
35
|
-
|
36
|
-
def trigger_callback_actions(method, type)
|
37
|
-
|
38
|
-
self.callback_actions_for(method, type).each do |callback|
|
28
|
+
def trigger_metaclass_callback_actions(method, type)
|
29
|
+
self.metaclass.callback_actions_for(method, type).each do |callback|
|
30
|
+
|
39
31
|
if callback.block
|
40
|
-
return instance_eval(&callback.block)
|
32
|
+
return self.instance_eval(&callback.block)
|
41
33
|
else
|
42
34
|
callback.proc.call
|
43
35
|
end
|
44
36
|
end
|
45
|
-
|
46
37
|
#Should I return something?
|
47
38
|
end
|
48
|
-
|
49
|
-
end
|
39
|
+
|
40
|
+
end #InstanceMethods
|
41
|
+
end #Callbacks
|
data/test/test_callbacks.rb
CHANGED
@@ -153,21 +153,6 @@ class CallbacksTest < Test::Unit::TestCase
|
|
153
153
|
assert_equal ['before_exit'], $tests_run
|
154
154
|
end
|
155
155
|
|
156
|
-
# def test_should_not_raise_error_when_method_not_exist
|
157
|
-
# assert_nothing_raised do
|
158
|
-
# Tester.add_callback_methods :doesnotexist
|
159
|
-
# end
|
160
|
-
# end
|
161
|
-
|
162
|
-
# def test_no_method_callback_should_not_add_method
|
163
|
-
# Tester.add_callback_methods :nomethodcallback
|
164
|
-
# t = Tester.new
|
165
|
-
#
|
166
|
-
# assert_raise NameError do
|
167
|
-
# t.nomethodcallback
|
168
|
-
# end
|
169
|
-
# end
|
170
|
-
|
171
156
|
def test_should_use_defined_methods_in_class_as_callback
|
172
157
|
Tester.add_callback_methods :callback_with_defined_method
|
173
158
|
t = Tester.new
|
@@ -185,16 +170,27 @@ class CallbacksTest < Test::Unit::TestCase
|
|
185
170
|
end
|
186
171
|
end
|
187
172
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
173
|
+
def test_callbacks_created_in_class_should_be_vissible_in_instance
|
174
|
+
Tester.add_callback_methods :boot, :exit
|
175
|
+
Tester.new
|
176
|
+
assert_equal [:boot, :exit], Tester.callback_methods
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_predefined_callback_methods_should_run_once
|
180
|
+
Tester.add_callback_methods :callback_with_defined_method
|
181
|
+
t = Tester.new
|
182
|
+
t.callback_with_defined_method
|
183
|
+
assert $tests_run.length == 1
|
184
|
+
end
|
193
185
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
186
|
+
def test_method_defined_after_include_should_work
|
187
|
+
Tester.send(:define_method, :after_include) do
|
188
|
+
$tests_run << 'after_include'
|
189
|
+
end
|
190
|
+
Tester.add_callback_methods :after_include
|
191
|
+
t = Tester.new
|
192
|
+
t.after_include
|
193
|
+
assert $tests_run.length == 1
|
194
|
+
end
|
199
195
|
|
200
196
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
class SingletonCallbacksTest < Test::Unit::TestCase
|
2
|
+
attr_accessor :tester
|
3
|
+
|
4
|
+
def setup
|
5
|
+
Object.send(:remove_const, :Tester) if defined? Tester
|
6
|
+
load 'test/tester_class.rb'
|
7
|
+
self.tester = Tester.new
|
8
|
+
$tests_run = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_should_create_instance_methods
|
12
|
+
tester.metaclass.add_callback_methods :boot
|
13
|
+
|
14
|
+
assert_nothing_raised { tester.boot }
|
15
|
+
assert_nothing_raised { tester.boot_without_callbacks }
|
16
|
+
assert_nothing_raised { tester.metaclass.before_boot('p "ehlo"') }
|
17
|
+
assert_nothing_raised { tester.metaclass.after_boot('p "ehlo"') }
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_class_should_create_before_and_after_method
|
21
|
+
tester.metaclass.add_callback_methods :boot
|
22
|
+
methods = tester.metaclass.methods.grep(/(^before_.+$|^after_.+$)/)
|
23
|
+
|
24
|
+
assert methods.include?('before_boot')
|
25
|
+
assert methods.include?('after_boot')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_callback_created_in_instance_should_not_be_vissible_in_class
|
29
|
+
tester.metaclass.add_callback_methods :boot
|
30
|
+
assert_equal [], Tester.callback_methods
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_callback_created_in_class_should_be_vissible_in_instance
|
34
|
+
#This ain't gonna work...
|
35
|
+
#I don't know how to get the variables
|
36
|
+
Tester.add_callback_methods :boot
|
37
|
+
t = Tester.new
|
38
|
+
assert_equal [:boot], t.metaclass.callback_methods
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_callbacks_created_in_class_and_instance_should_both_be_run
|
42
|
+
Tester.add_callback_methods :boot
|
43
|
+
Tester.before_boot do
|
44
|
+
$tests_run << 'before_boot'
|
45
|
+
end
|
46
|
+
|
47
|
+
tester.metaclass.after_boot do
|
48
|
+
$tests_run << 'after_boot'
|
49
|
+
end
|
50
|
+
|
51
|
+
tester.boot
|
52
|
+
|
53
|
+
assert $tests_run.include?('before_boot')
|
54
|
+
assert $tests_run.include?('after_boot')
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_callbacks_created_in_class_and_instance_should_both_be_run_2
|
58
|
+
Tester.add_callback_methods :boot
|
59
|
+
Tester.before_boot do
|
60
|
+
$tests_run << 'before_boot'
|
61
|
+
end
|
62
|
+
|
63
|
+
tester.metaclass.before_boot do
|
64
|
+
$tests_run << 'before_boot_2'
|
65
|
+
end
|
66
|
+
|
67
|
+
tester.boot
|
68
|
+
|
69
|
+
assert $tests_run.include?('before_boot')
|
70
|
+
assert $tests_run.include?('before_boot_2')
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_singleton_callbacks_on_clean_object
|
74
|
+
a = Object.new
|
75
|
+
a.metaclass.send(:include, Callbacks)
|
76
|
+
a.metaclass.add_callback_methods :to_s
|
77
|
+
a.metaclass.before_to_s do
|
78
|
+
$tests_run << 'clean!'
|
79
|
+
end
|
80
|
+
a.to_s #and see the magic happen
|
81
|
+
|
82
|
+
assert $tests_run.length == 1
|
83
|
+
assert $tests_run[0] == 'clean!'
|
84
|
+
end
|
85
|
+
end
|
data/test/tester_class.rb
CHANGED
@@ -2,6 +2,7 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
|
|
2
2
|
require 'callbacks'
|
3
3
|
|
4
4
|
class Tester
|
5
|
+
include Callbacks
|
5
6
|
|
6
7
|
def boot
|
7
8
|
return "booting"
|
@@ -27,6 +28,5 @@ class Tester
|
|
27
28
|
def fill_globalvar_tests_run
|
28
29
|
$tests_run << 'fill_globalvar_tests_run'
|
29
30
|
end
|
30
|
-
|
31
|
-
include Callbacks
|
31
|
+
|
32
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: callbacks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leon Bogaert
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-10-14 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- test/profile.rb
|
52
52
|
- test/test_callbacks.rb
|
53
53
|
- test/test_helper.rb
|
54
|
+
- test/test_singleton_callbacks.rb
|
54
55
|
- test/tester_class.rb
|
55
56
|
has_rdoc: true
|
56
57
|
homepage: www.vanutsteen.nl
|
@@ -76,10 +77,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
77
|
requirements: []
|
77
78
|
|
78
79
|
rubyforge_project: callbacks
|
79
|
-
rubygems_version: 1.
|
80
|
+
rubygems_version: 1.3.0
|
80
81
|
signing_key:
|
81
82
|
specification_version: 2
|
82
83
|
summary: This package makes it simple to add callbacks a
|
83
84
|
test_files:
|
84
85
|
- test/test_helper.rb
|
86
|
+
- test/test_singleton_callbacks.rb
|
85
87
|
- test/test_callbacks.rb
|