On 7/14/06, ara.t.howard / noaa.gov <ara.t.howard / noaa.gov> wrote:
> On Fri, 14 Jul 2006, Sean O'Halpin wrote:
>
> > Hmmm. I'm still getting "singleton method called for a different
> > object (TypeError)" for this (ruby 1.8.4 (2005-12-24) [i386-mswin32]).
>
> me too.
>
>    harp:~ > cat a.rb
>    class X # role of IO
>      class << self
>        def x(*args,&block) # role of open
>            block.call(1764) if block
>        end
>      end
>    end
>
>    OLD = X.method :x
>
>    class Y < X # role of File
>      class << self
>        def x; "rubbish"; end
>      end
>    end
>
>    class Y
>      class << self
>        define_method(:x, OLD )
>      end
>    end
>
>    Y.x{|a| puts a }
>
>
>    harp:~ > ruby a.rb
>    a.rb:23:in `x': singleton method called for a different object (TypeError)
>            from a.rb:23
>
>
>    harp:~ > ruby -v && cat /etc/redhat-release && uname -srm
>    ruby 1.8.4 (2005-12-01) [i686-linux]
>    Red Hat Enterprise Linux WS release 3 (Taroon Update 7)
>    Linux 2.4.21-40.EL i686
>
> you robert?
>
>
> btw.  this challenge was not arbitrary:  the increase in metaprogramming
> popularity means people are doing things like
>
>    def class_method
>      alias '__instance_method__', 'instance_method' # push
>
>      define_method 'instance_method' do
>        # ...
>        __instance_method__ 42
>        # ...
>      end
>
>    ensure
>      alias 'instance_method', '__instance_method__' # pop
>    end
>
> but this is neither thread safe (easy to fix) or re-entrant (not easy to fix).
> what i mean is doing
>
>    class_method{
>      class_method{
>      }
>    }
>
> blows up.
>
> to avoid this i wanted to develop this pattern
>
>    def class_method
>      __instance_method__ = method 'instance_method' # push
>
>      define_method 'instance_method' do
>        # ...
>        __instance_method__.call 42
>        # ...
>      end
>
>    ensure
>      define_method 'instance_method', __instance_method__ # pop
>    end
>
> but, of course, we are seeing that it doesn't work.
>
> regards.
>
> -a
> --
> suffering increases your inner strength.  also, the wishing for suffering
> makes the suffering disappear.
> - h.h. the 14th dali lama
>
>

In most cases, this works:

class Foo
  def self.open(*args, &block)
    p [args, block]
    yield if block_given?
  end
end

Foo.open(1) do
  puts "hello"
end

open_m = Foo.method 'open'

class Foo
  def self.open(*a) p 42 end
end

Foo.open(2) do
  puts "hello"
end

(class << Foo; self; end).instance_eval do
  define_method(:open, open_m)
end

Foo.open(3) do
  puts "bye"
end
__END__
[[1], #<Proc:0x02869018@c:/rubylib/experiments/redefine-class-method.rb:8>]
hello
42
[[3], #<Proc:0x02867728@c:/rubylib/experiments/redefine-class-method.rb:26>]
bye

but as we've seen, it doesn't work in the case of the File(IO)
singleton. To be honest, I'm not clear about exactly what kind of
object the File(IO) singleton is. Anyone offer any enlightenment?

Regards,
Sean