作为官方网站,我定义了两个模型Post
和Comment
。 Comment
嵌套在Post
。
resources :posts do
resources :comments
end
所以我可以使用@post.comments
来访问帖子所拥有的所有评论。在控制台中:
$ post = Post.new()
$ post.comments.class
> Array
可是:
$ post.comments.respond_to?("build")
> true
为什么呢?数组的方法是build
? Rails是怎么做的?我如何知道post.comments
的其他隐藏方法?
答案 0 :(得分:1)
首先,您的resources
调用位于routes.rb
文件中,该文件仅处理Rails的URL解析端。这与您的模型之间的关联无关,这些关联是使用相关模型文件中的has_many
和belongs_to
调用设置的。暂时忽略路线文件,因为它与问题的主要部分无关。
关于关联,您会发现post.comments
没有向您返回Array
,它实际上返回了ActiveRecord::Relation
个对象。 Relation
对象就像一个数组 - 实际上你在其上调用的任何非关系特定的方法(如build
)实际上都传递给了{{ 1}} Array
内容的表示。因此,当您调用Relation
时,post.comments.length
关联对象正在其内部数组上调用comments
。
其中一个后果是,调用.length
实际上也会传递对{Array}的post.comments.class
调用!
那么,.class
对象实际上可以做什么?由于该关联是通过Relation
电话设置的,因此您可以在has_many
documentation中找到答案。类似地,has_many
关联
答案 1 :(得分:0)
在ruby中,您可以添加或更改任何对象中的任何方法。您甚至可以向字符串实例添加新方法,例如:
x = "xyzzy"
x.name # => NoMethodError: undefined method `name' for "xyzzy":String
x.instance_eval do
class << self
define_method(:name) {"I got a name"}
end
end
x.class # => String
x.name # => "I got a name"
y = "other"
y.class # => String
y.name # => NoMethodError: undefined method `name' for "other":String
build
方法可能已被“添加”到由comments
访问者返回的由has_many
宏创建的Array实例。 (正如Gareth指出的那样,Rails使事情变得复杂,并且关联不会以这种方式工作。但是,与作为透明代理工作相比,扩展对象可能是一种更“干净”的方式。考虑我的例子作为红宝石相关,而非铁路)
至于问题的第二部分,您可以通过访问其methods
函数来了解给定对象的方法。它返回为此对象定义的所有(公共)方法的名称。 (如果您想要私有的,请参阅private_methods
功能。)
在我的示例x.methods
中还会包含新定义的“名称”方法,但y.methods
不会。
ruby中还有其他功能,您可以使用它们检查对象。您可以在Ruby API documentation找到它们。 API可能在各种版本的ruby中有一些(通常是轻微的)更改。请参阅您正在使用的版本的文档。
如果你想检查一些方法的代码,那么它可能有点问题,因为函数的“可执行代码”可能通过多种方式创建:它可能是一个副本(别名)< / em>的另一个函数,可以使用eval
函数动态创建,依此类推。
知道方法的名称,你可以'grep'你可用的源代码,也许你想要的方法还没有动态创建。
我看到项目ParseTree仍然存在。如果你真的想知道你没有来源的函数的代码,也许你会觉得它很有帮助。