Monkeypatching multiple classes with similar methods

L

Lars Olsson

Hello!

I'm trying to monkeypatch a number of related classes that all
implements the same method (meth). The methods all take one required
argument (stuff) but some of the individual methods may require more
arguments (or a block). All I want to do in each call to meth is to
print some debug data and then pass the incoming arguments to the
original method. This works great as long as I know the exact number
of arguments required, but when the number of arguments starts to
change my code breaks badly. Is there any way (in ruby 1.8.7) to
"copy" the original method signature when defining my own replacement
method?

/lasso

--- CODE START ---
class Klass1
def meth(stuff)
puts "You've sent #{stuff} to #{self.class}.meth"
end
end

class Klass2
def meth(stuff, &block)
block_text = block_given? ? 'with' : 'without'
puts "You've sent #{stuff} to #{self.class}.meth #{block_text} a
block"
end
end

class Klass3
def meth(stuff, morestuff)
puts "You've sent #{stuff} to #{self.class}.meth"
end
end

# Broken monkeypatching. Only works on Klass1
[Klass1, Klass2, Klass3].each do |klass|
klass.module_eval do
alias_method :eek:riginal_meth, :meth
def meth(stuff)
puts "#{self.class}.meth has been patched"
original_meth(stuff)
end
end
end

Klass1.new.meth('one')
Klass2.new.meth('two') { 'three' } # Block is not passed after
monkeypatching
Klass2.new.meth('four')
Klass3.new.meth('five', 'six') # Raises ArgumentError after
monkeypatching
--- CODE END ---
 
E

Ehsanul Hoque

Hey. You just have a tiny couple of bugs. Try this instead (untested=2C but=
you get the idea):

[Klass1=2C Klass2=2C Klass3].each do |klass|
klass.module_eval do
alias_method :eek:riginal_meth=2C :meth
def meth(*stuff=2C &block)
puts "#{self.class}.meth has been patched"
original_meth(*stuff=2C &block)
end
end
end
Date: Tue=2C 22 Sep 2009 17:45:06 +0900
From: (e-mail address removed)
Subject: Monkeypatching multiple classes with similar methods
To: (e-mail address removed)
=20
Hello!
=20
I'm trying to monkeypatch a number of related classes that all
implements the same method (meth). The methods all take one required
argument (stuff) but some of the individual methods may require more
arguments (or a block). All I want to do in each call to meth is to
print some debug data and then pass the incoming arguments to the
original method. This works great as long as I know the exact number
of arguments required=2C but when the number of arguments starts to
change my code breaks badly. Is there any way (in ruby 1.8.7) to
"copy" the original method signature when defining my own replacement
method?
=20
/lasso
=20
--- CODE START ---
class Klass1
def meth(stuff)
puts "You've sent #{stuff} to #{self.class}.meth"
end
end
=20
class Klass2
def meth(stuff=2C &block)
block_text =3D block_given? ? 'with' : 'without'
puts "You've sent #{stuff} to #{self.class}.meth #{block_text} a
block"
end
end
=20
class Klass3
def meth(stuff=2C morestuff)
puts "You've sent #{stuff} to #{self.class}.meth"
end
end
=20
# Broken monkeypatching. Only works on Klass1
[Klass1=2C Klass2=2C Klass3].each do |klass|
klass.module_eval do
alias_method :eek:riginal_meth=2C :meth
def meth(stuff)
puts "#{self.class}.meth has been patched"
original_meth(stuff)
end
end
end
=20
Klass1.new.meth('one')
Klass2.new.meth('two') { 'three' } # Block is not passed after
monkeypatching
Klass2.new.meth('four')
Klass3.new.meth('five'=2C 'six') # Raises ArgumentError after
monkeypatching
--- CODE END ---
=20
=0A=
_________________________________________________________________=0A=
Microsoft brings you a new way to search the web. Try Bing=99 now=0A=
http://www.bing.com?form=3DMFEHPG&publ=3DWLHMTAG&crea=3DTEXT_MFEHPG_Core_ta=
gline_try bing_1x1=
 
L

Lars Olsson

Hey. You just have a tiny couple of bugs. Try this instead (untested, butyou get the idea):

[Klass1, Klass2, Klass3].each do |klass|
  klass.module_eval do
    alias_method :eek:riginal_meth, :meth
    def meth(*stuff, &block)
      puts "#{self.class}.meth has been patched"
      original_meth(*stuff, &block)
    end
  end
end




Date: Tue, 22 Sep 2009 17:45:06 +0900
From: (e-mail address removed)
Subject: Monkeypatching multiple classes with similar methods
To: (e-mail address removed)

I'm trying to monkeypatch a number of related classes that all
implements the same method (meth). The methods all take one required
argument (stuff) but some of the individual methods may require more
arguments (or a block). All I want to do in each call to meth is to
print some debug data and then pass the incoming arguments to the
original method. This works great as long as I know the exact number
of arguments required, but when the number of arguments starts to
change my code breaks badly. Is there any way (in ruby 1.8.7) to
"copy" the original method signature when defining my own replacement
method?

--- CODE START ---
class Klass1
  def meth(stuff)
    puts "You've sent #{stuff} to #{self.class}.meth"
  end
end
class Klass2
  def meth(stuff, &block)
    block_text = block_given? ? 'with' : 'without'
    puts "You've sent #{stuff} to #{self.class}.meth #{block_text} a
block"
  end
end
class Klass3
  def meth(stuff, morestuff)
    puts "You've sent #{stuff} to #{self.class}.meth"
  end
end
# Broken monkeypatching. Only works on Klass1
[Klass1, Klass2, Klass3].each do |klass|
  klass.module_eval do
    alias_method :eek:riginal_meth, :meth
    def meth(stuff)
      puts "#{self.class}.meth has been patched"
      original_meth(stuff)
    end
  end
end
Klass1.new.meth('one')
Klass2.new.meth('two') { 'three' } # Block is not passed after
monkeypatching
Klass2.new.meth('four')
Klass3.new.meth('five', 'six') # Raises ArgumentError after
monkeypatching
--- CODE END ---

_________________________________________________________________
Microsoft brings you a new way to search the web.  Try  Bing™ nowhttp://www.bing.com?form=MFEHPG&publ=WLHMTAG&crea=TEXT_MFEHPG_Core_ta....bing_1x1- Dölj citerad text -

- Visa citerad text -

Exactly what I needed (and even simpler than I though). Your solution
works perfectly. Thank you!

/lasso
 
E

Ehsanul Hoque

Exactly what I needed (and even simpler than I though). Your solution
works perfectly. Thank you!
=20
/lasso
=20

You're welcome! I'm just glad to be of service to the ruby community (final=
ly). =3D)
=0A=
_________________________________________________________________=0A=
Hotmail=AE has ever-growing storage! Don=92t worry about storage limits.=0A=
http://windowslive.com/Tutorial/Hotmail/Storage?ocid=3DTXT_TAGLM_WL_HM_Tuto=
rial_Storage_062009=
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top