First question: How do I get the the method passed?
Eg.
cat test1.rb #-------------------------
class Dog
def bark
‘arf!arf!’
end
def method_missing(x)
p “method missing”
“sorry, cannot do #{x} in #{self}”
end
end
beethoven = Dog.new
p beethoven.bark
p beethoven.purr #-------------------------
ruby -w test1.rb
“arf!arf!”
“sorry, cannot do purr in #Dog:0x2777228”
I’d like a method similar to method_missing(x) (wherein the methodname
is
passed in x), but only access it before a method is run (maybe name it
method_called(x)).
So I can do (maybe),
…
Class Dog
…
def method_called(x)
p “You ask for #{x}”
end
end
Another option is to use a similar scheme as in Delegator and
automatically
generate proxy methods that invoke your “method_called” just before they
hand over control to the real method. http://www.rubycentral.com/book/lib_patterns.html
Which of the approaches you choose depends on your situation.
Tehre might be another option to define a module / class method that
automatically creates a new method that first invokes method_called and
the
the original method. Sorryy, I don’t have the time at the moment to put
such a thing together.
Cancel that. This works:
class Module
def notify(sym)
new_sym = “#{sym}_old”.intern
alias_method new_sym.to_s, sym.to_s
define_method sym do |*args|
puts "#{sym} called with args: #{args.inspect}"
send( new_sym, *args )
end
class Module
def notify(sym)
new_sym = “#{sym}_old”.intern
alias_method new_sym.to_s, sym.to_s
define_method sym do |*args|
Isn’t it a shame that you cannot propagate blocks with define_method?
Maybe we could use Kernel.block_given, with the obvious semantics.
puts "#{sym} called with args: #{args.inspect}"
send( new_sym, *args )
end
end
end
class Foo
def bar
yield
puts “bar!”
end
notify :bar
end
Foo.new.bar { puts “Bomb” }
batsman@tux-chan:/tmp$ ruby f.rb
f.rb:24: warning: block for Proc#bar is useless
bar called with args:
f.rb:17:in bar_old': no block given (LocalJumpError) from f.rb:9:in send’
from f.rb:9:in bar' from f.rb:7:in bar’
from f.rb:24
···
On Sun, Jan 25, 2004 at 05:04:58AM +0900, Robert Klemme wrote:
class Module
def notify(sym)
new_sym = “#{sym}_old”.intern
alias_method new_sym.to_s, sym.to_s
define_method sym do |*args|
Isn’t it a shame that you cannot propagate blocks with
define_method?
Yeah, that’s true. I ran into it while figuring how to do it.
What would you think about Kernel::block_given, returning a Proc
corresponding to the block or nil?
I don’t like it because it imposes the additional overhead of a proc
creation even for cases when you just want the boolean information. How
about extending Proc to accept blocks like this:
proc {|foo, &bl|
puts “foo=#{foo}”
bl.call if bl
}
Or at least extend Proc#call to use blocks. Currently this is what
happens:
irb(main):063:0> proc {|*args| p args; p block_given? ; yield }
…call(1,2,3) { puts “block!” }
[1, 2, 3]
false
LocalJumpError: no block given
from (irb):63
from (irb):63:in `call’
from (irb):63
Matz, this is not too big a change, is it?
Regards
robert
···
On Sun, Jan 25, 2004 at 10:14:56PM +0900, Robert Klemme wrote:
On Sun, Jan 25, 2004 at 05:04:58AM +0900, Robert Klemme wrote:
from :0
We have Kernel.block_given? already… so having Kernel.block_given too
seems most natural to me, and it looks easier to implement than adding
an optional &block to the block args.
···
On Mon, Jan 26, 2004 at 07:55:00PM +0900, Robert Klemme wrote:
What would you think about Kernel::block_given, returning a Proc
corresponding to the block or nil?
I don’t like it because it imposes the additional overhead of a proc
creation even for cases when you just want the boolean information. How
about extending Proc to accept blocks like this:
What would you think about Kernel::block_given, returning a Proc
corresponding to the block or nil?
I don’t like it because it imposes the additional overhead of a proc
creation even for cases when you just want the boolean information.
How
about extending Proc to accept blocks like this:
We have Kernel.block_given? already… so having Kernel.block_given too
seems most natural to me, and it looks easier to implement than adding
an optional &block to the block args.
Oha, I guess it is as susceptible for typos as my eyes reading your
posting: I read “block_given?” which I embarrassed have to admit was not
what you wrote. Sorry for that.
Still I’d prefer the other approach (using “&b” to get the block or
allowing to “yield”) because it is more consistent with the current
software and has not this just-one-character-difference gotcha.
Regards
robert
···
On Mon, Jan 26, 2004 at 07:55:00PM +0900, Robert Klemme wrote: