I have a module which I include in a class using Module#extend. That
module defines an instance method which returns the name of the module
that defined the method. Currently, I do that by hard-coding the string
into the method definition, but it seems that there should really be a
better way.
Here’s some code:
irb(main):001:0> module Awesome
irb(main):002:1> def who_am_i
irb(main):003:2> ‘Awesome’ # Repeating myself, bad!
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> class One
irb(main):007:1> def initialize(what)
irb(main):008:2> extend what
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> a = One.new(Awesome)
=> #One:0x40322710
irb(main):012:0> a.who_am_i
=> “Awesome”
I have a module which I include in a class using Module#extend. That
module defines an instance method which returns the name of the module
that defined the method. Currently, I do that by hard-coding the string
into the method definition, but it seems that there should really be a
better way.
The string is simple though… but if you want another way you could
look at Module#ancestors on the singleton class (since you use
extend).
module A end
a = “some_object”.extend A #=> “abc”
singleton_class = class << a; self end # #<Class:#String:...>
singleton_class.ancestors #=> [A, String, Enumerable, Comparable,
Object, Kernel]
singleton_class.ancestors.first #=> A
If you want it in string form:
singleton_class.ancestors.first.to_s #=> “A”
You would want to wrap this up in some sort of method (at least the
class << part).
module Awesome
s = self
define_method(“who_am_i”) { s }
end
obj = Object.new
obj.extend(Awesome)
p obj.who_am_i # Awesome
There’s a bit of semantic weirdness in the object claiming to be the
module But anyway, that’s one way to get the module object into
one of its own instance methods.
IMHO this is a bad idea because you cannot change layout that way
multiple
times. Once you extended an instance by a module this module stays in
place
even if you extend with a different module. Also, a Window has a
layout -
so composition is far more appropriate here than inheritance. And if
you do
that and model layouts as independent class hierarchy you can simply use
the
layout instance’s class or it’s name for the layout name.
a = Window.new
a.layout = CoolLayout
puts “This window has the layout #{a.layout_name}”
I’d prefer to let the layout answer the question after its name which
also
nicely fits with the composition approach - and it helps keep the
interface
of Window focused:
puts “This window has the layout #{a.layout.name}”
Kind regards
robert
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.