【问题标题】:Where do I define symbols so that they're accessible in another model?我在哪里定义符号以便它们可以在另一个模型中访问?
【发布时间】:2012-08-20 02:06:31
【问题描述】:

在这里的优秀系列文章中:http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/comment-page-2/#comment-908 他解释了一点关于如何使用 devise 进行身份验证和 cancan 获得权限。我有一个看起来简单得多的问题(所以那些文章中省略了):

我应该在哪里定义诸如 :super_admin 这样的符号,以便技能类可以访问它们?这些定义应该如何看待?

我很确定这些定义属于 Role 类,但如果是这样,它们在 Ability 类中如何(在范围内)简单地使用 :super_admin ?

【问题讨论】:

    标签: ruby-on-rails devise ruby-on-rails-3.2 cancan


    【解决方案1】:

    您可以将符号视为类似于常量的高效字符串。你没有明确定义它们,你只是使用它们——这可能是你感到困惑的地方。此外,由于您“仅使用”符号,因此它们没有范围。如果您将符号输入错误为:duper_admin,则不会对其进行错误检查,因为 ruby​​ 会很乐意为您创建该符号。

    在文章中,作者在roles 表中定义角色。那么如何将数据库中的角色与您的角色符号(例如:super_admin)进行比较?通过使用这种方法

    def role?(role)
      return !!self.roles.find_by_name(role.to_s.camelize)
    end
    

    这样用的

    if user.role? :super_admin
      can :manage, :all
    ...
    

    role? 方法只是将符号转换为字符串,以便可以将其与数据库中的值进行比较。 roles 表和所使用的符号之间没有进行编程映射。它们只是手动保持同步。

    【讨论】:

    • 符号 :super_admin 什么时候才有意义?那么,当您在示例中的 if 块中调用代码时, :super_admin 会被传递给角色吗?方法。此方法将查看用户是否分配了此角色,但它会搜索什么角色?它说它会搜索...我明白了,to_s 将 :super_admin 更改为“super_admin”,然后 camelize 将其更改为“SuperAdmin”,这意味着我需要一个在数据库中名为“SuperAdmin”的角色。哇,一定累了,谢谢你的帮助。
    【解决方案2】:

    符号的意义在于 ruby​​ 解释器只为每个符号创建一个副本。如果您在一个 ruby​​ 文件中写入 :foo,它将与所有其他 ruby​​ 文件中的所有其他 :foo 相同。您不必提前定义或声明符号。

    【讨论】:

    • 所以当我检查用户是否关联了特定角色时,ruby 将如何将数据库中的值与符号进行比较?