【发布时间】:2016-08-01 03:54:14
【问题描述】:
我有一个名为User 的类,它是has_many: roles, through: user_roles。我正在尝试为用户类中的关联角色元编程谓词方法,如下所示:
class User < ActiverRecord::Base
...
Role.all.pluck(:name).each do |role_name|
define_method("#{role_name}?") do
roles.map(&:name).include?(role_name)
end
end
...
end
虽然Role.all.pluck(&:name) 确实返回了一个现有角色名称的数组,但define_method 永远不会被调用,并且我的规范因未定义的方法而失败:
...
subject.roles << create(:role, name: 'foo')
expect(subject.foo?).to be true #<= undefined method `foo?' for #<User...>
...
【问题讨论】:
-
应该是
pluck(:name),没有&。这可能会破坏集合的构建,导致define_method永远不会被调用。 -
@sixty4bit 哎呀,更新了。我决定用
pluck替换.map,却忘了删除to_proc。但是仍然返回undefined method -
啊哈。在那种情况下,我认为答案可能更根本地在于元编程是如何工作的。您的
Role.all...逻辑在User类加载时执行,即在测试运行之前。因此,将定义的唯一方法将用于在加载User之前已经存在的角色。在User加载后,在测试中创建角色不会对之前运行的代码产生任何影响。希望这是有道理的......
标签: ruby-on-rails ruby metaprogramming predicate