我刚刚在rails上学习ruby,我有一个用户角色表(所有者,管理员和用户)。在代码中将有一些地方需要检查用户的角色并显示不同的选项。有没有人知道怎么做而不诉诸魔术数字或其他丑陋的方法?
在ASP.Net网络应用程序中,我已经通过使用枚举类型看到了这一点:
public enum UserRole { Owner = 1, Admin = 2, User = 3 }
// ...
if (user.Role == UserRole.Admin)
// Show special admin options
数据库中的每个不同角色都反映为枚举类型,其值设置为数据库中该角色的ID。这似乎不是一个非常好的解决方案,因为它取决于可能会改变的数据库知识。即使这是处理这样的事情的正确方法,我也不知道如何在rails中使用枚举类型。
我很感激对此事的任何见解。
答案 0 :(得分:26)
Ruby本身没有枚举类型,但此站点显示方法http://www.rubyfleebie.com/enumerations-and-ruby/
您可以在用户模型中制作类似的内容:
#constants
OWNER = 1
ADMIN = 2
USER = 3
def is_owner?
self.role == OWNER
end
def is_admin?
self.role == ADMIN
end
def is_user?
self.role == USER
end
答案 1 :(得分:12)
Rails 4.1中添加的功能是否可以满足您的要求?
http://coherence.io/blog/2013/12/17/whats-new-in-rails-4-1.html
从博客文章中复制:
class Bug < ActiveRecord::Base
# Relevant schema change looks like this:
#
# create_table :bugs do |t|
# t.column :status, :integer, default: 0 # defaults to the first value (i.e. :unverified)
# end
enum status: [ :unverified, :confirmed, :assigned, :in_progress, :resolved, :rejected, :reopened ]
...
Bug.resolved # => a scope to find all resolved bugs
bug.resolved? # => check if bug has the status resolved
bug.resolved! # => update! the bug with status set to resolved
bug.status # => a string describing the bug's status
bug.status = :resolved # => set the bug's status to resolved
答案 2 :(得分:4)
这似乎是使用我的classy_enum宝石的一个非常好的案例。它本质上允许您定义一组固定的选项,其中每个选项都是具有特定于其的行为和属性的类。它有助于减少所有在整个应用程序中分散的条件逻辑。
例如,如果你这样做:
class User < ActiveRecord::Base
def options
if user.is_admin?
[...admin options...]
else
[...non admin options...]
end
end
end
然后在其他地方呼叫:user.options
......
classy_enum允许您将该逻辑移动到一个单独的位置,并且具有相同的功能而没有条件逻辑:
class User < ActiveRecord::Base
classy_enum_attr :role
delegate :options, :to => :role
end
README有一个工作示例,详细描述了宝石。
答案 3 :(得分:2)
我喜欢在这种情况下使用恰当命名的Authorization插件。
这会让你
permit "role"
限制对角色的访问,
permit? "role"
简单地测试访问权限。这两个都委托给User#has_role?(role)
。
不要觉得你必须使用他们的ObjectRoles
实现。您可以使用Hardwired
角色,然后实施自己的User#has_role?(role)
方法来使用现有架构。
答案 4 :(得分:2)
刚开始学习Rails(来自C#),并且有完全相同的问题。似乎Rails并不真正有枚举因为哲学不同。我会使用大量的枚举来尝试组织C#项目中的所有细节,但也许因为Rails为你处理这么多,所以它们并不那么重要。这不是一个真正的答案,只是一个观察。
答案 5 :(得分:0)
rubyforge上有一个enum plugin所以你可以这样做:
t.column :severity, :enum, :limit => [:low, :medium, :high, :critical]
使用:limit
属性传递参数非常难看,但这是一种更标准化的方式。
安装只需执行:
script/plugin install svn://rubyforge.org/var/svn/enum-column/plugins/enum-column
它当前适用于Rails 2.2.2或更高版本。 Rubyforge链接:www.rubyforge.org/projects/enum-column /