Get mixin's name

A somewhat weird situation.

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"

-Payton

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).

Brian.

···

On 12/28/05, Payton Swick <payton@foolord.com> wrote:

A somewhat weird situation.

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.

Hi --

A somewhat weird situation.

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"

Does this help?

   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 :slight_smile: But anyway, that's one way to get the module object into
one of its own instance methods.

David

···

On Thu, 29 Dec 2005, Payton Swick wrote:

--
David A. Black
dblack@wobblini.net

"Ruby for Rails", from Manning Publications, coming April 2006!

A somewhat weird situation.

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"

-Payton

If you want to find out the defining class of a method you can use #method:

module Awesome; def foo() end end

=> nil

class One; include Awesome; end

=> One

One.new.method(:foo).to_s

=> "#<Method: One(Awesome)#foo>"

Btw, what do you need that for?

Kind regards

    robert

···

Payton Swick <payton@foolord.com> wrote:

The goal was basically this for a GUI (the answer is probably that there's a better way):

module Layout
# ... layout stuff
def layout_name
'none'
end

module CoolLayout
include Layout
# ... override some layout stuff.
def layout_name
'CoolLayout' # Not DRY
end

class Window
def layout=(l)
extend l
end

a = Window.new
a.layout = CoolLayout
puts "This window has the layout #{a.layout_name}"

-Payton

Robert Klemme wrote:

···

Payton Swick <payton@foolord.com> wrote:

A somewhat weird situation.

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"

-Payton

If you want to find out the defining class of a method you can use #method:

module Awesome; def foo() end end

=> nil

class One; include Awesome; end

=> One

One.new.method(:foo).to_s

=> "#<Method: One(Awesome)#foo>"

Btw, what do you need that for?

Kind regards

   robert

The goal was basically this for a GUI (the answer is probably that
there's a better way):

module Layout
# ... layout stuff
def layout_name
'none'
end

module CoolLayout
include Layout
# ... override some layout stuff.
def layout_name
'CoolLayout' # Not DRY
end

class Window
def layout=(l)
extend l
end

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

···

Payton Swick <payton@foolord.com> wrote: