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…
class Lmao
def initialize
@str = "HAHAHAHAHAHHAHAHAH"
end
def self.inherited(base)
base.extend(Callbacks)
end
def laughing
self.class.callbacks_before_laughing.each {|method| send(method)
} @str
end
end
module Callbacks
def before_laughing(*methods)
@before_laughing = methods
end
def callbacks_before_laughing
@before_laughing
end
end
class Lol < Lmao
before_laughing :downcase_please
def downcase_please
@str.downcase!
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.
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!!
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):
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.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.