考虑到我在每个数据库中都有以下类和一些记录:
class User < ActiveRecord::Base
has_many :user_roles
has_many :roles, :through => :user_roles
end
class Role < ActiveRecord::Base
has_many :user_roles
has_many :users, :through => :user_roles
def self.method1
"boo!"
end
end
为什么User.first.roles.method1
成功运作?我以为User.first.roles返回一个Array
,其类没有定义method1。
> User.first.roles.method1
=> "boo!"
当然,Role.all.method1
会按照我的预期抛出未定义的方法错误。
我的堆栈:Ruby 1.9.3p484,Rails 3.2.13
答案 0 :(得分:1)
User.first.roles将返回您的数组,因此您无法在数组上调用您的方法
您可以调用此类方法
User.first.roles.collect{|role| role.method1}
答案 1 :(得分:1)
实际上它不是一个数组。 它是ActiveRecord :: Associations :: CollectionProxy 你可以在这里查看定义 activerecord / lib / active_record / associations / collection_proxy.rb
它更改了method_missing,它将所有请求发送到父类。
答案 2 :(得分:1)
好的 - 我明白你现在在问什么 - 我想包括我在内的很多人都对这个问题感到困惑,抱歉。我认为这种混乱是因为你重写了这个问题,因为“我能做到这一点”是一个非常模糊和广泛的问题。
我认为你所要求的,具体而言,可以改为“如果我在一个Role对象数组上调用一个Role类级别方法(”method1“),从User.first.roles
返回,然后它返回调用Role.method1
的结果相同。不应该失败,因为Array没有那个方法吗?“
答案是当rails返回关联的结果时,它会混合一个模块(或更可能是一堆模块),这会增加额外的方法。其中一种方法是method_missing,它试图在已经收集的类上调用该方法。所以,它仍然是一个数组,但它是一个带有额外方法的数组。
如果你想看看它发生了什么,把raise "BANG!"
放在你的method1方法中,然后再次调用你的代码:在堆栈跟踪中,你将能够看到魔法发生的位置。
答案 3 :(得分:0)
在Ruby中,您可以使用“map”方法(也就是“收集” - 我更喜欢“收集”自己)来调用相同的方法(或者更一般地,运行相同的代码块),因为在Java是一个“地图”,我们称之为ruby中的“哈希”。
例如
User.first.roles.map{|role| role.method1}
=> #an array of the values of method1
我不确定这是不是你想做的,你的问题不是很清楚。
编辑:我刚想到你想在一个角色而不是数组上调用method1。在那种情况下,你可以说User.first.roles.first.method1
假设您确实想要第一个角色对象。