roles_mask 如何在 rails 中工作

How does roles_mask work in rails

按照 railscasts 189 Embedded Association 上的教程设置我的应用程序。所以就像我在教程中添加的那样

t.Integer :roles_mask

我的用户 table 以及以下我的模型

class User < ApplicationRecord

    ROLES = %w[admin moderator author]

    def roles= (roles)
        self.roles_mask = (roles & ROLES).map { |r| 2** ROLES.index(r) }.sum
    end

    def roles
        ROLES.reject { |r| ((roles_mask || 0) & 2** ROLES.index(r)).zero? }
    end

    def role_symbols
        roles.map(& :to_sym )
    end
end

使用表单添加和删除角色一切正常。但是我怎样才能从控制台实现这一点呢?它究竟是如何工作的,rails 如何从整数值中识别字符串角色?

啊哈!我最喜欢的逻辑!是bits的魔法。在机器语言中,一切都以零和一 (0-1) 表示。现在回到角色

ROLES = %w[admin moderator author]

对于模型中指定的每个角色,它分配一位。

admin moderator author 
1     1         1

对于用户实例,如果您给他该角色,则该位变为 1 else 0

u = User.new
u.roles = [:admin]
u.admin? #=> true
u.roles_mask #=> 1
admin moderator author 
1     0         0
# Read it in reverse as 0 0 1 which in binary means 1. That's why roles_mask is 1
u.roles << :author
u.roles_mask #=> 5
admin moderator author 
1     0         1
# Read it as 1 0 1 which in binary means 5. That's why roles_mask is 5

所以,它只是有点神奇,没有其他东西可以维护角色分配 :) 阅读更多关于二进制到十进制转换的信息 here

如果您看到 role_model gem 的 README,它会提到:

# declare the valid roles -- do not change the order if you add more
# roles later, always append them at the end!

这正是它提到的季节。如果您更改顺序,持久值为 1 的用户将不知道您做了什么!