很难将 `is_x?` 别名为 `has_role? x`
每个用户有多个角色;要查明用户是否具有“admin”角色,我们可以使用 has_role?
方法:
some_user.has_role?('admin')
其定义如下:
def has_role?(role_in_question)
roles.map(&:name).include?(role_in_question.to_s)
end
我希望能够将 some_user.has_role?('admin')
写为 some_user.is_admin?
,所以我这样做了:
def method_missing(method, *args)
if method.to_s.match(/^is_(\w+)[?]$/)
has_role? $1
else
super
end
end
这对于 来说效果很好some_user.is_admin?
案例,但当我尝试在另一个关联中引用的用户上调用它时失败:
>> Annotation.first.created_by.is_admin?
NoMethodError: undefined method `is_admin?' for "KKadue":User
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_proxy.rb:215:in `method_missing'
from (irb):345
from :0
什么给出?
Each user has many roles; to find out whether a user has the "admin" role, we can use the has_role?
method:
some_user.has_role?('admin')
Which is defined like this:
def has_role?(role_in_question)
roles.map(&:name).include?(role_in_question.to_s)
end
I'd like to be able to write some_user.has_role?('admin')
as some_user.is_admin?
, so I did:
def method_missing(method, *args)
if method.to_s.match(/^is_(\w+)[?]$/)
has_role? $1
else
super
end
end
This works fine for the some_user.is_admin?
case, but fails when I try to call it on a user referenced in another association:
>> Annotation.first.created_by.is_admin?
NoMethodError: undefined method `is_admin?' for "KKadue":User
from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_proxy.rb:215:in `method_missing'
from (irb):345
from :0
What gives?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Rails 检查您是否
respond_to?在
。发送
之前输入“is_admin?”因此,您需要专门化
respond_to?
,例如:注意:不要问我为什么 Rails 检查
respond_to?
而不是仅仅在那里进行send
,我看不出有什么好的理由。另外:最好的方法(Ruby 1.9.2+)是定义
respond_to_missing?
来兼容所有版本,例如:Rails checks if you
respond_to? "is_admin?"
before doing asend
.So you need to specialize
respond_to?
also like:Note: Don't ask me why rails checks for
respond_to?
instead of just doing asend
there, I don't see a good reason.Also: The best way (Ruby 1.9.2+) is to define
respond_to_missing?
instead, and you can be compatible with all versions with something a bit fancy like:ActiveRecord::Associations::AssociationProxy
类会重写method_missing
并在您要查找的调用到达模型之前拦截该调用。发生这种情况是因为 AP 检查模型是否
respond_to?
方法,在您的情况下,它没有。除了编辑 Rails 的源代码之外,您还有一些解决方案:
首先,使用元编程为用户对象手动定义每个 is_* 方法。类似于:
另一种方法是通过其他方式加载用户对象,例如
或使用列出的其他答案之一。
The
ActiveRecord::Associations::AssociationProxy
class overridesmethod_missing
and intercepts the call you are looking for before it gets to the model.This happens because AP checks if the model
respond_to?
the method, which in your case, it doesn't.You have a few solutions aside from editing Rails' source:
First, manually define each of the is_* methods for the user object using metaprogramming. Something like:
Another is to load the User object via some other means such as
Or use one of the other answers listed.