1

I'm trying to retrieve the parameters for a couple instance methods. The idiomatic Ruby way to do this is like so:

class A
  def test(id)
    puts id
  end
end

A.instance_method(:test).parameters

#=> [[:req, :id]]

This approach works most of the time, however I get some strange returns with certain methods and I have no idea why.

module Events
  class Repository
    def find(id)
      #code
    end
    def delete(id)
      #code
    end
  end
end

Events::Repository.instance_method(:find).parameters
#=> [[:req, :id]]

Events::Repository.instance_method(:delete).parameters
#=> [[:rest, :args], [:block, :block_for_method]]

Is this a Ruby bug?

NOTE: I'm typing the above into the Rails console.

fbonetti
  • 6,652
  • 3
  • 34
  • 32
  • 1
    I was unable to reproduce this using Rails console for Rails 3.2.13 and ruby 2.0.0p247 in Linux. Do you get different results if you change the class name to something random like Banana? What does `Events::Repository.ancestors` show? What does `Events::Repository.instance_method(:delete)` show? Maybe there is a module prepended that defined `delete`. What version of Ruby and what version of Rails are you using? – David Grayson Jul 17 '13 at 17:42

1 Answers1

1

I don't know exactly why you are getting the behavior, but if you answer the questions from my earlier comment we can probably figure it out.

However, as an answer to your question I can say already that it is not necessarily a bug in Ruby. Here is an example of a small ruby program that would give the same kind of output you are getting:

module X
  def delete(*args, &block)
  end
end

class Y
  prepend X
end    

class Y   # reopen the existing class
  def delete(x)
  end
end

p Y.instance_method(:delete)   # => #<UnboundMethod: Y(X)#delete>
p Y.instance_method(:delete).parameters # => [[:rest, :args], [:block, :block]]
David Grayson
  • 84,103
  • 24
  • 152
  • 189
  • Yes, that seems to be the issue. I'm using the Aquarium gem which implements the Aspect-Oriented pattern, allowing me run methods after specific methods are run (similar to "before_filter" and "after_filter" in Rails controllers). It appears to prepend, like you suggested. Do you know if there is any way around this? – fbonetti Jul 17 '13 at 18:03
  • Also, I believe "Y" should actually be "X" in the last two lines of your post. – fbonetti Jul 17 '13 at 18:04
  • No, I meant to say Y. Y is the class that you opened up and added a `delete` method to, and Y corresponds to `Events::Repository` in your example. I do not know of any way to isolate the `delete` method defined in Y and figure out how many methods you have. Perhaps this is a missing feature of Ruby. However, you haven't told me what you are actually trying to accomplish so I suspect there is probably a much better way to do it, without using reflection. Or maybe you could just rename the method you probe to something other than `delete`. – David Grayson Jul 18 '13 at 16:31