ruby-callbacks 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/ruby-callbacks.rb +194 -0
  2. metadata +46 -0
@@ -0,0 +1,194 @@
1
+ # module Callbackable allows to add callbacks
2
+ # before and after methods
3
+ #
4
+ # == Example
5
+ #
6
+ # require "ruby-callbacks"
7
+ #
8
+ # class Cat
9
+ # include Callbacks
10
+ #
11
+ # attr_accessor :name, :colour
12
+ #
13
+ # callback :after, :eat, :play
14
+ # callback :before, :eat, :sleep
15
+ #
16
+ # def initialize(name, colour)
17
+ # @name = name
18
+ # @colour = colour
19
+ # end
20
+ #
21
+ # def sleep
22
+ # puts "#{@name} the cat is sleeping"
23
+ # end
24
+ #
25
+ # def eat
26
+ # puts "#{@name} the cat is eating"
27
+ # end
28
+ #
29
+ # def play
30
+ # puts "#{@name} the cat is playing"
31
+ # end
32
+ #
33
+ # end
34
+ #
35
+ # kitty = Cat.new("Kitty", "black")
36
+ #
37
+ # kitty.eat
38
+ # # => Kitty the cat is sleeping
39
+ # # => Kitty the cat is eating
40
+ # # => Kitty the cat is playing
41
+
42
+ module Callbacks
43
+
44
+ class UnknownEventException < Exception; end
45
+
46
+ # md5 for word "method"
47
+ SALT = "ea9f6aca279138c58f705c8d4cb4b8ce"
48
+
49
+ def self.included(base)
50
+
51
+ base.class_eval do
52
+ @@_method_chain = Hash.new
53
+ @@_callbacks_running = Array.new
54
+ # show current_method_chain
55
+ def self.method_chain
56
+ @@_method_chain
57
+ end
58
+
59
+ # allows to add a callback to already initialized class
60
+ # == Example
61
+ # class Cat
62
+ # include Callbacks
63
+ #
64
+ # def purr
65
+ # # purr
66
+ # end
67
+ #
68
+ # def sleep
69
+ # # sleep
70
+ # end
71
+ # end
72
+ #
73
+ # Cat.add_callback(:after, :purr, :sleep)
74
+ # Cat.new.purr # purr, then sleep
75
+ def self.add_callback(event, method, callback)
76
+ if callbacks_exist? method
77
+ callback(event, method, callback)
78
+ else
79
+ callback(event, method, callback)
80
+ run_callback(method)
81
+ end
82
+ end
83
+
84
+ # Delete existing callback
85
+ # if callback == nil deletes all callbacks on given *method*
86
+ # == Example
87
+ # class Cat
88
+ # include Callbacks
89
+ # callback :after, :purr, :sleep
90
+ # def purr
91
+ # # purr
92
+ # end
93
+ #
94
+ # def sleep
95
+ # # sleep
96
+ # end
97
+ # end
98
+ #
99
+ # Cat.callbacks_exist?(:purr) # => true
100
+ # Cat.del_callback(:purr)
101
+ # Cat.callbacks_exist?(:purr) # => false
102
+ def self.del_callback(method, callback = nil)
103
+ if callback
104
+ @@_method_chain[method].delete_if{|c| c == callback }
105
+ del_all_callbacks(method) if @@_method_chain[method].size == 1
106
+ else
107
+ del_all_callbacks(method)
108
+ end
109
+ end
110
+
111
+ # Are callback *callback* on this method already exists?
112
+ def self.callback_exists?(method, callback)
113
+ !@@_method_chain[method.to_sym].detect{|c| c == callback.to_sym }.nil?
114
+ end
115
+
116
+ # Are callbacks on this method already exists?
117
+ def self.callbacks_exist?(method)
118
+ !@@_method_chain[method.to_sym].nil?
119
+ end
120
+
121
+ class << self
122
+ def new_method_name(method)
123
+ "#{method}_#{SALT}"
124
+ end
125
+
126
+ def method_added(method)
127
+ if callbacks_exist?(method) && !@@_callbacks_running.include?(method)
128
+ run_callback(method)
129
+ end
130
+ end
131
+
132
+ private
133
+ # Register new callback
134
+ # See main example
135
+ def callback(event, method, callback)
136
+ reg_callback(event.to_sym, method.to_sym, callback.to_sym)
137
+ end
138
+
139
+ def del_all_callbacks(method)
140
+ undef_method method
141
+ alias_method method, new_method_name(method)
142
+ @@_callbacks_running.delete_if {|m| m == method}
143
+ @@_method_chain[method] = nil
144
+ end
145
+
146
+ def run_callback(method)
147
+ return if @@_callbacks_running.include? method
148
+ alias_method new_method_name(method), method
149
+ undef_method method
150
+
151
+ @@_callbacks_running.push method
152
+
153
+ define_method method do
154
+ call_method_chain(method)
155
+ end
156
+ end
157
+
158
+ def reg_callback(event, method, callback)
159
+ raise UnknownEventException if (event != :before && event != :after)
160
+ @@_method_chain[method] = [new_method_name(method)] unless @@_method_chain[method]
161
+
162
+ if event === :before
163
+ reg_before_callback(method, callback)
164
+ elsif event === :after
165
+ reg_after_callback(method, callback)
166
+ end
167
+ end
168
+
169
+ def reg_before_callback(method, callback)
170
+ @@_method_chain[method].insert \
171
+ (@@_method_chain[method].index new_method_name(method)), callback
172
+ end
173
+
174
+ def reg_after_callback(method, callback)
175
+ @@_method_chain[method].push callback
176
+ end
177
+
178
+ end
179
+
180
+ def call_method_chain(method)
181
+ result = nil
182
+ @@_method_chain[method].each do |action|
183
+ if action == self.class.new_method_name(method)
184
+ result = self.send(action)
185
+ else
186
+ self.send(action)
187
+ end
188
+ end
189
+ return result
190
+ end
191
+
192
+ end
193
+ end
194
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-callbacks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ilya Boltnev
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-30 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: module Callbackable allows to add callbacks before and after methods
15
+ email:
16
+ - ilya@boltnev.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/ruby-callbacks.rb
22
+ homepage: https://github.com/boltnev/ruby-callbacks
23
+ licenses: []
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 1.8.25
43
+ signing_key:
44
+ specification_version: 3
45
+ summary: This is a gem for providing callbacks
46
+ test_files: []