Class: Jetpants::Callback
Overview
Generic representation of a before-method or after-method callback. Used internally by CallbackHandler; you won’t need to interact with Callback directly.
Constant Summary collapse
- @@all_callbacks =
hash of class obj -> method_name symbol -> type string -> array of callbacks
{}
- @@currently_wrapping =
hash of class obj -> method_name symbol -> bool
{}
Instance Attribute Summary collapse
-
#for_class ⇒ Object
readonly
class object.
-
#method_name ⇒ Object
readonly
symbol containing method name (the one being callback-wrapped).
-
#my_alias ⇒ Object
readonly
method name alias OF THE CALLBACK.
-
#priority ⇒ Object
readonly
high numbers get triggered first.
-
#type ⇒ Object
readonly
:before or :after.
Class Method Summary collapse
- .trigger(for_object, method_name, type, *args) ⇒ Object
- .wrap_method(for_class, method_name) ⇒ Object
- .wrapped?(for_class, method_name) ⇒ Boolean
Instance Method Summary collapse
-
#initialize(for_class, method_name, type = :after, priority = 100) ⇒ Callback
constructor
A new instance of Callback.
Constructor Details
#initialize(for_class, method_name, type = :after, priority = 100) ⇒ Callback
Returns a new instance of Callback.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/jetpants/callback.rb', line 67 def initialize(for_class, method_name, type=:after, priority=100) @for_class = for_class @method_name = method_name @type = type @priority = priority @@all_callbacks[for_class] ||= {} @@all_callbacks[for_class][method_name] ||= {} already_wrapped = Callback.wrapped?(for_class, method_name) @@all_callbacks[for_class][method_name][type] ||= [] next_method_id = @@all_callbacks[for_class][method_name][type].count + 1 old_name = "#{type.to_s}_#{method_name.to_s}".to_sym @my_alias = new_name = ("real_callback_#{old_name}_" + for_class.to_s.sub('::', '_') + "_#{next_method_id}").to_sym for_class.class_eval do alias_method new_name, old_name end Callback.wrap_method(for_class, method_name) unless already_wrapped @@all_callbacks[for_class][method_name][type] << self end |
Instance Attribute Details
#for_class ⇒ Object (readonly)
class object
61 62 63 |
# File 'lib/jetpants/callback.rb', line 61 def for_class @for_class end |
#method_name ⇒ Object (readonly)
symbol containing method name (the one being callback-wrapped)
62 63 64 |
# File 'lib/jetpants/callback.rb', line 62 def method_name @method_name end |
#my_alias ⇒ Object (readonly)
method name alias OF THE CALLBACK
65 66 67 |
# File 'lib/jetpants/callback.rb', line 65 def my_alias @my_alias end |
#priority ⇒ Object (readonly)
high numbers get triggered first
64 65 66 |
# File 'lib/jetpants/callback.rb', line 64 def priority @priority end |
#type ⇒ Object (readonly)
:before or :after
63 64 65 |
# File 'lib/jetpants/callback.rb', line 63 def type @type end |
Class Method Details
.trigger(for_object, method_name, type, *args) ⇒ Object
115 116 117 118 119 120 121 122 123 124 |
# File 'lib/jetpants/callback.rb', line 115 def self.trigger(for_object, method_name, type, *args) my_callbacks = [] for_object.class.ancestors.each do |for_class| if @@all_callbacks[for_class] && @@all_callbacks[for_class][method_name] && @@all_callbacks[for_class][method_name][type] my_callbacks.concat(@@all_callbacks[for_class][method_name][type]) end end my_callbacks.sort_by! {|c| -1 * c.priority} my_callbacks.each {|c| for_object.send(c.my_alias, *args)} end |
.wrap_method(for_class, method_name) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/jetpants/callback.rb', line 89 def self.wrap_method(for_class, method_name) @@currently_wrapping[for_class] ||= {} @@currently_wrapping[for_class][method_name] ||= false return if @@currently_wrapping[for_class][method_name] # prevent infinite recursion from the alias_method call @@currently_wrapping[for_class][method_name] = true for_class.class_eval do alias_method "#{method_name}_without_callbacks".to_sym, method_name define_method method_name do |*args| begin Callback.trigger(self, method_name, :before, *args) rescue CallbackAbortError return end result = send "#{method_name}_without_callbacks".to_sym, *args begin Callback.trigger(self, method_name, :after, *args) rescue CallbackAbortError end result end end @@currently_wrapping[for_class][method_name] = false end |
.wrapped?(for_class, method_name) ⇒ Boolean
126 127 128 129 |
# File 'lib/jetpants/callback.rb', line 126 def self.wrapped?(for_class, method_name) return false unless @@all_callbacks[for_class] && @@all_callbacks[for_class][method_name] @@all_callbacks[for_class][method_name].count > 0 end |