I've got some troubles with Ruby about callbacks (and inheritance). Here
is my code:
class Lmao
def initialize @str = "HAHAHAHAHAHHAHAHAH" @before_laughing = []
end
def self.inherited(base)
base.extend(Callbacks)
end
def laughing @before_laughing.each {|method| send(method) } @str
end
end
module Callbacks
def before_laughing(*methods) @before_laughing = methods
end
end
class Lol < Lmao
before_laughing :downcase_please
def downcase_please @str.downcase!
end
end
a = Lol.new
a.laughing # => "HAHAHAHAHAHHAHAHAH"
And as you can see, my before laughing callback don't work... because
the array @before_laughing is empty. I believe this can be fixed by
editing the way I save *methods into an Lol's instance method (from
inside Callbacks). But I don't really see how...
The problem is that before_laughing is being invoked as a class method on
Lol. So when you say "before_laughing :downcase_please", you aren't setting @before_laughing on instances of Lol, but rather on Lol itself.
I suppose one way to do this is to leave the instance var on the class, then
just ask the class for its contents and execute them the same way. With this
implementation, that means you can't add callbacks for individual objects,
though.
class Lmao
def initialize @str = "HAHAHAHAHAHHAHAHAH"
end
def self.inherited(base)
base.extend Callbacks
end
def laughing
self.class.before_laughing.each do |method|
send method
end @str
end
end
module Callbacks
def before_laughing(*methods)
if methods.empty? @before_laughing ||= Array.new
else @before_laughing = methods
end
end
end
The problem is that before_laughing is being invoked as a class method
on
Lol. So when you say "before_laughing :downcase_please", you aren't
setting @before_laughing on instances of Lol, but rather on Lol itself.
Okay.
I suppose one way to do this is to leave the instance var on the
class, then just ask the class for its contents and execute them
the same way.
Using your code, I have the same result then Mon_Ouie, with one less
method in the code and no errors when a callback isn't called. It's just
so cool.
With this implementation, that means you can't add callbacks
for individual objects, though.
However, I am not sure to understand this point. I believe I can do it.
Here I tried to add different callbacks on different classes (and every
thing is working find):
class Lol < Lmao
before_laughing :downcase_please
?> def downcase_please
@str.downcase!
end
end
=> nil
?> a = Lol.new
=> #<Lol:0x101f11448 @str="HAHAHAHAHAHHAHAHAH">
a.laughing
=> "hahahahahahhahahah"
?> class Lool < Lmao
before_laughing :add_ok
?> def add_ok
@str.concat("_ok")
end
end
=> nil
?> b = Lool.new
=> #<Lool:0x101ee9448 @str="HAHAHAHAHAHHAHAHAH">
b.laughing
=> "HAHAHAHAHAHHAHAHAH_ok"
?> class Loool < Lmao
before_laughing :add_ok, :downcase_please
?> def add_ok
@str.concat("_ok")
end
?> def downcase_please
@str.downcase!
end
end
=> nil
?> c = Loool.new
=> #<Loool:0x101eb4310 @str="HAHAHAHAHAHHAHAHAH">
c.laughing
=> "hahahahahahhahahah_ok"
But if I understand correctly, I can not do so by class instance...
Well, okay. For my needs, it's just perfect anyway. Thank you!!
I mean that you can't add a callback for a given instance of the class.
Every instance of Lol will have the same before_laughing callbacks. It
shouldn't be too much more work to give them the ability to have such
behaviour, if you need it, I just thought I should point it out since your
initial implementation seemed to assume that the @before_laughing was set on
each instance.
···
On Thu, Dec 30, 2010 at 12:02 PM, Satsou Sa <moshimoshi.here@gmail.com>wrote:
> With this implementation, that means you can't add callbacks
> for individual objects, though.
However, I am not sure to understand this point. I believe I can do it.
Here I tried to add different callbacks on different classes (and every
thing is working find):
----
class Lmao
def initialize @str = "HAHAHAHAHAHHAHAHAH"
end
def laughing @str
end
=begin
def self.inherited(base)
base.extend(Callbacks)
end
=end
end
module Callbacks
def before_laughing(*methods)
define_method(:laughing) do
methods.each do |m|
send(m)
end
super
end
end
end
class Lol < Lmao
extend Callbacks
before_laughing :downcase_please
def downcase_please @str.downcase!
end
end