是否可以干掉以下代码:
def is_user?
is_role? ROLES[:user]
end
def is_mod?
is_role? ROLES[:mod]
end
def is_admin?
is_role? ROLES[:admin]
end
private
def is_role?(role)
self.roles & role == role
end
进入单个函数,但仍然能够将函数名称调用为当前函数(is_user?
,is_mod?
等)
更新
使用Aetherus'回答下面我创建了以下用于管理用户角色(用户可以拥有多个角色):
class User < ActiveRecord::Base
# Use bitwise values for more roles (double the previous values)
ROLES = { user: 1, dummy: 2, mod: 4, admin: 8 }
# Add the desired role
def add_role(role)
self.roles |= ROLES[role]
end
# eg: add_role :admin
# Removed the desired role
def remove_role(role)
self.roles &= ~ROLES[role]
end
# methods for each role (mod? admin? etc)
ROLES.keys.each do |role|
define_method("#{role}?") do
self.roles & ROLES[role] == ROLES[role]
end
end
end
答案 0 :(得分:4)
您可以使用一个ruby代码块定义多个方法。
%w(user mod admin).each do |role|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def #{role}?
role == '#{role}' && roles.include?('#{role}')
end
RUBY
end
或者更明确的方式:
%w(user mod admin).each do |role|
define_method("#{role}?") do
self.role == role && roles.include?(role)
end
end
顺便说一句,在ruby中,不需要is_
前缀,因为尾随?
告诉程序员该方法返回true
或false
。< / p>
答案 1 :(得分:2)
您可以使用method_missing
。
最简单的解决方案是:
class Roles
def method_missing(method_name, *args, &block)
if /^is_(?<role_name>\w+)\?$/ =~ method_name
is_role?(role_name.to_sym)
else
super
end
end
private
def is_role?(role_name)
# just for demo purposes
p "Checking #{role_name}"
end
end
roles = Roles.new
roles.is_user?
roles.is_mod?
roles.is_admin?
在method_missing
我正在尝试捕获任何未实现的方法(请注意,我删除了正确的方法is_user?
,is_mod?
和{ {1}}),稍后,我正在检查方法的名称是否与正则表达式(is_admin?
)的正确的格式,如果是,我正在重用捕获的{{ 1}}。
稍微限制/^is_(?<role_name>\w+)\?$/
。
这种方法的问题是,它会接受任何方法调用,比如说role_name
。在某些情况下,这可能是可取的,有时则不是。如果您只想将其限制为您提到的3种类型的用户,可以将Regex更改为:
method_missing
最后一件事。在实施is_super_user?
时,您还应该注意/^is_(user|mod|admin)\?$/
,当您想要断言对象是否响应那些魔术方法时,这是非常关键的:
method_missing
有了这个,你就可以做到:
respond_to_missing?
了解更多here。
希望有所帮助!
答案 2 :(得分:0)
@Jacob,如果您使用rails 4,则可以使用AR#enum功能(http://api.rubyonrails.org/classes/ActiveRecord/Enum.html),无需手动实现。