When I say method_defined? I mean it!

I’ve been bitten by this way too many times now. And I’m just plain
tired of it.

Today’s case:

def wrap_method( sym, &blk )
raise ArgumentError, “method does not exist – #{sym}” unless
method_defined?( sym )
old = instance_method(sym)
define_method(sym) { |*args| blk.call(old.bind(self), *args) }
end

Seems all well and good until now when it comes out that
#method_defined?, like #instance_methods, does something only a Ruby
hacker without a life would expect. The actual monster code needed
is:

def wrap_method( sym, &blk )
unless public_method_defined?( sym ) || private_method_defined?(
sym ) || protected_method_defined?( sym )
raise ArgumentError, “method does not exist – #{sym}”
end
old = instance_method(sym)
define_method(sym) { |*args| blk.call(old.bind(self), *args) }
end

Now, it just doesn’t stand to any good reason. When we wan’t to
actually grab a method, we don’t use #public_instance_method, do we?
That would be a nightmare! And so it is with the above case and many
others I’ve delt with. Every time I have to go back and fix this “bug”
recalling the terribly inconvenient and anti-literal definition of
these methods-methods.

T.

def wrap_method( sym, &blk )
raise ArgumentError, “method does not exist – #{sym}” unless method_defined?( sym )
old = instance_method(sym)
define_method(sym) { |*args| blk.call(old.bind(self), *args) }
end

Replace “unless method_defined?( sym )” with “unless
(method(sym) rescue nil)”.

But you don’t need this check. instance_method(sym), on the
next line, already performs this check for you.

gegroet,
Erik V. - http://www.erikveen.dds.nl/

I think Mr. Veenstra’s approach is fine–either allow the exception
from instance_method() to percolate up, or rescue it and throw your
own. As far as a comprehensive check goes, wouldn’t ‘unless
method_defined? || private_method_defined?’ suffice? Or you could, I
guess, use

unless Object.new.extend(self).respond_to?(sym, true)

which seems more amusing.

Erik V. wrote:

def wrap_method( sym, &blk )
raise ArgumentError, “method does not exist – #{sym}” unless method_defined?( sym )
old = instance_method(sym)
define_method(sym) { |*args| blk.call(old.bind(self), *args) }
end

Replace “unless method_defined?( sym )” with “unless
(method(sym) rescue nil)”.

Tha won’t work b/c it would be looking at the module or classes
methods, not the instance methods.

But you don’t need this check. instance_method(sym), on the
next line, already performs this check for you.

Oh right, thanks, I’ll change.

Nonetheless if I wanted to do something else with the check, the point
of my post remains. It silly to have to check

public_methods || private_methods || protected_methods

When #instance_methods should just correspond to the behavior to
#instance_method. I mean, isn;t reasonable to think those two methods
would have the same lookup behavior?

T.

Dumaiu wrote:

I think Mr. Veenstra’s approach is fine–either allow the exception
from instance_method() to percolate up, or rescue it and throw your
own. As far as a comprehensive check goes, wouldn’t ‘unless
method_defined? || private_method_defined?’ suffice? Or you could, I
guess, use

unless Object.new.extend(self).respond_to?(sym, true)

which seems more amusing.

I think my point is being missed. Forget my last example, it has
nothing to do with it --it was just a special case --one in which I
didn’t end up needing to check if the method existed b/c it was going
to do what I was telling it do anyway. I could just as easily taken a
different route.

My point is about the semantic meaning of important methods about
methods. Think about it like Dr. Suess. Let’s say I have these methods:

big_fish #=> [ “tuna”, “saw” ]
small_fish #=> [ “trout”, “croaker” ]
tiny_fish #=> [ “beta” ]

So what woud expect from just:

fish #=> ?

T.

Tempting as it is to respond to Dr. Seuss, I think it makes more
sense to ask you to state your point as succinctly as possible so as to
prevent further misunderstanding. I’m guessing you dislike the fact
that method_defined?() doesn’t consider private methods–?

-J

Dumaiu wrote:

Tempting as it is to respond to Dr. Seuss, I think it makes more
sense to ask you to state your point as succinctly as possible so as to
prevent further misunderstanding. I’m guessing you dislike the fact
that method_defined?() doesn’t consider private methods–?

:slight_smile: Yes --and protected. method_defined? is one of the culprits, and so
are #methods and #instance_methods. Here’s my Dr. Seuss analogy
de-anaologized:

public_instance_methods #=> [ “tuna”, “saw” ]
private_instance_methods #=> [ “trout”, “croaker” ]
protected_instance_methods #=> [ “beta” ]

So what woud expect from just:

instance_methods #=> ?

T.

A quick test I did in irb suggests that methods(),
instance_methods() and method_defined?() all register protected
members, meaning that only the, uh, privates are omitted. I concede
that it can be confusing, but there’s no point submitting a RCR without
an understanding of the current rationale. I suppose the idea is that
because private methods are implementational, you shouldn’t have to see
them without specifically asking. Of course, prohibiting access would
be out of character for Ruby; hence the optional respond_to?()
parameter.
I might like having an optional switch for instance_methods(), too,
but in all I think the setup is satisfactorily logical and consistent.
My thinking on the matter is a bit clearer now. How about you?

-J

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs