ruby-callbacks 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.
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: []