2013-07-17 156 views
0

我想检索几个实例方法的参数。惯用的Ruby的方式来做到这一点,像这样:如何获取实例方法参数?

class A 
    def test(id) 
    puts id 
    end 
end 

A.instance_method(:test).parameters 

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

这种方法适用的大部分时间,但是我得到的某些方法的一些奇怪的回报,我不知道为什么。

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]] 

这是Ruby错误吗?

注意:我在Rails控制台中输入上面的内容。

+1

我无法重现为Rails 3.2.13本使用Rails控制台,并在Linux中红宝石2.0.0p247。如果您将课程名称更改为随机喜欢的香蕉,您会得到不同的结果吗? 'Events :: Repository.ancestors'显示了什么? “Events :: Repository.instance_method(:delete)'show是什么?也许有一个模块预先定义了'delete'。你使用的是什么版本的Ruby和Rails的版本? –

回答

1

我不确切地知道你为什么会得到这种行为,但如果你回答我之前评论中的问题,我们大概可以弄明白。

但是,作为您的问题的答案,我可以说已经不是Ruby中的错误。这里是一个小Ruby程序会给出相同的输出类型你得到的一个例子:

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]] 
+0

是的,这似乎是问题。我正在使用实现Aspect-Oriented模式的Aquarium gem,允许我在运行特定方法后运行方法(类似于Rails控制器中的“before_filter”和“after_filter”)。它似乎预先支配,就像你所建议的那样。你知道有没有办法解决这个问题? – fbonetti

+0

另外,我相信“Y”在你的文章的最后两行应该是“X”。 – fbonetti

+0

不,我的意思是说Y.Y是你打开的类,并在你的例子中添加了一个'delete'方法,Y对应于'Events :: Repository'。我不知道有什么办法来隔离Y中定义的'delete'方法,并找出你有多少种方法。也许这是Ruby的一个缺失功能​​。然而,你没有告诉我你实际上想要完成什么,所以我怀疑可能有更好的方法去做,而不使用反射。或者,也许你可以将你探测的方法重命名为“delete”以外的其他方法。 –