How to force a method redefinition?

Hello,
i'm puzzeld by the following piece of code:

$ cat tests.rb
                                          
module B
  def xx ; puts "in B" ; end
end
module C
  def xx ; puts "in C"; end
end
module D
  def xx ; puts "in D"; end
end

include B ; xx
include C ; xx
include D ; xx
include B ; xx
include C ; xx

$ ruby ./tests.rb
in B
in C
in D
in D
in D

I expected
in B
in C
in D
in B
in C

looks like include's are made only once.

Is there another way of getting what i expect ?

thanks

Denis

"dm1" <dmertz@online.de> schrieb im Newsbeitrag news:d5tq7n$sq3$1@online.de...

Hello,
i'm puzzeld by the following piece of code:

$ cat tests.rb

module B
def xx ; puts "in B" ; end
end
module C
def xx ; puts "in C"; end
end
module D
def xx ; puts "in D"; end
end

include B ; xx
include C ; xx
include D ; xx
include B ; xx
include C ; xx

$ ruby ./tests.rb
in B
in C
in D

I expected
in B
in C
in D
in B
in C

looks like include's are made only once.

Is there another way of getting what i expect ?

There are several ways. You can for example fetch methods from a module with "B.instance_method :xx" and then bind it to an instance. What do you need that for?

Kind regards

    robert

Robert Klemme wrote:

There are several ways. You can for example fetch methods from a module
with "B.instance_method :xx" and then bind it to an instance. What do you
need that for?

It is for my internationalization project (ri18n). I have two versions of a
set of translator methods, they are contained in modules
Translators::Normal and Translators::Fallback

I'd like to be able to dynamically include one or the other of these modules
into other classes/modules (this works ok with include) and then again
eventually 're-include' the other version (Translators::Fallback -->
Translators::Normal) This does not work with plain old 'include'.

Anyway, i will try with your "B.instance_method :xx" tip

Thanks

Denis

···

Kind regards

    robert

Robert Klemme schrieb:

There are several ways. You can for example fetch methods from a module with "B.instance_method :xx" and then bind it to an instance. What do you need that for?

I guess that would work out

···

---
module FRedef
    def self.extended(mod)
        mod.instance_eval do
            @instance_methods = Hash.new
            instance_methods(false).each do |sym|
                @instance_methods[sym] = instance_method(sym)
                remove_method(sym)
            end
        end
    end
    private
    def append_features(mod)
        @instance_methods.each do |sym,mth|
            mod.__send__(:define_method,sym,mth)
        end
        super
    end
end

module B
    def xx ; puts "in B" ; end
    extend FRedef
end

module C
def xx ; puts "in C"; end
extend FRedef
end

module D
def xx ; puts "in D"; end
extend FRedef
end

include B ; xx
include C ; xx
include D ; xx
include B ; xx
include C ; xx
---
Note with the -w option you'll get redefinition warnings -
check out singleton.rb on how to avoid this.

/Christoph

It works nice. Thanks

Denis

Christoph wrote:

···

I guess that would work out
---
module FRedef
    def self.extended(mod)
        mod.instance_eval do
            @instance_methods = Hash.new
            instance_methods(false).each do |sym|
                @instance_methods[sym] = instance_method(sym)
                remove_method(sym)
            end
        end
    end
    private
    def append_features(mod)
        @instance_methods.each do |sym,mth|
            mod.__send__(:define_method,sym,mth)
        end
        super
    end
end

module B
    def xx ; puts "in B" ; end
    extend FRedef
end

module C
def xx ; puts "in C"; end
extend FRedef
end

module D
def xx ; puts "in D"; end
extend FRedef
end

include B ; xx
include C ; xx
include D ; xx
include B ; xx
include C ; xx
---
Note with the -w option you'll get redefinition warnings -
check out singleton.rb on how to avoid this.

/Christoph