【问题标题】:How does roles_mask work in railsRoles_mask 如何在 Rails 中工作
【发布时间】:2018-03-10 12:04:56
【问题描述】:
按照 railscasts 189 Embedded Association 上的教程设置我的应用程序。所以就像我在教程中添加的一样
t.Integer :roles_mask
到我的用户表和以下到我的模型
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 是如何从整数值中识别字符串角色的?
【问题讨论】:
标签:
ruby-on-rails
authorization
roles
【解决方案1】:
啊哈!我最喜欢的逻辑!是bits的魔法。在机器语言中,一切都以零和一 (0-1) 呈现。现在回到角色
ROLES = %w[admin moderator author]
对于模型中指定的每个角色,它分配一个位。
admin moderator author
1 1 1
对于用户实例,如果您给他该角色,则该位变为1 否则为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,它会提到:
# 声明有效角色 -- 如果添加更多,请不要更改顺序
# 个角色之后,始终将它们附加到最后!
这正是它提到的季节。如果您更改订单,则持久值为1 的用户不会知道您做了什么!