Rails枚举类型或替代

时间:2009-05-26 04:17:58

标签: ruby-on-rails enums

我刚刚在rails上学习ruby,我有一个用户角色表(所有者,管理员和用户)。在代码中将有一些地方需要检查用户的角色并显示不同的选项。有没有人知道怎么做而不诉诸魔术数字或其他丑陋的方法?

在ASP.Net网络应用程序中,我已经通过使用枚举类型看到了这一点:

public enum UserRole { Owner = 1, Admin = 2, User = 3 }

// ...

if (user.Role == UserRole.Admin)
    // Show special admin options

数据库中的每个不同角色都反映为枚举类型,其值设置为数据库中该角色的ID。这似乎不是一个非常好的解决方案,因为它取决于可能会改变的数据库知识。即使这是处理这样的事情的正确方法,我也不知道如何在rails中使用枚举类型。

我很感激对此事的任何见解。

6 个答案:

答案 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)

ruby​​forge上有一个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 /