导轨 4 |使用位掩码在表单中为用户分配角色 |榜样

Posted

技术标签:

【中文标题】导轨 4 |使用位掩码在表单中为用户分配角色 |榜样【英文标题】:Rails 4 | Assign Role to User in Form using Bitmask | RoleModel 【发布时间】:2014-10-27 05:41:40 【问题描述】:

我陷入了以下问题 - 我怀疑有一个简单的解决方案,但我就是想不通。

我在 Rails 4 中使用Role Model Gem。

一切正常,分配的角色作为内部位掩码完美地存储在用户模型的角色掩码属性(整数)中。

现在,我希望管理员可以通过 FORM(视图)分配和删除用户的角色。我不是 Rails Ninja,所以可能有一个技巧可以做到这一点。

根据文档,我可以执行以下操作:

# role assignment
>> u.roles = [:admin]  # ['admin'] works as well
=> [:admin]

# adding roles (remove via delete or re-assign)
>> u.roles << :manager
=> [:admin, :manager]

这样就明白了。

我的方法是查询表单中的所有有效角色:

# get all valid roles that have been declared
>> User.valid_roles
=> [:admin, :manager, :author]

然后将它们列为复选框。提交表单后,我分配/删除角色。

问题: 这是正确的方法吗,这是否有效,如果有效,如何?

【问题讨论】:

我通过引入 attr_accessor 并为每个角色创建一个虚拟属性暂时解决了这个问题。然后我根据角色(取消)设置复选框。保存后,我会检查哪些值已更改并相应地添加/删除角色。这似乎有点矫枉过正,但它确实有效。如果有人有更好的解决方案,请告诉我!谢谢。 【参考方案1】:

既然我没有找到方法就遇到了问题 - 这是解决方案:

更多详情here.

每个用户的多个角色

我在此答案中假设您具有符号形式的角色(在下面我修改了此解决方案以使其与符号一起使用) - 因此可以使用 Pundit 以防您使用它。

# in models/user.rb
ROLES = [:admin, :manager, :general, :custom_role, :another_custome_role, :banned]

可以为用户分配多个角色并使用位掩码将其存储到单个整数列中。首先在您的 users 表中添加一个 roles_mask 整数列。

rails 生成迁移 add_roles_mask_to_users roles_mask:integer 耙分贝:迁移 接下来,您需要将以下代码添加到 User 模型中,以获取和设置用户所属的角色列表。这将执行必要的按位运算,将角色数组转换为整数字段。

# in models/user.rb
def roles=(roles)
  self.roles_mask = (roles & ROLES).map  |r| 2**ROLES.index(r) .inject(0, :+)
end

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

这里稍作修改以使其与 Rolify & Pundit 一起使用

  def roles=(roles)
    self.roles_mask = (roles.map  |x| x.to_sym  & ROLES).map  |r| 2**ROLES.index(r) .inject(0, :+)
  end

如果您使用的设计没有强参数,请不要忘记将 attr_accessible :roles 添加到您的用户模型中。

如果您使用带有 strong_parameters 的设计,无论是作为 Rails 3 应用程序中的 gem,还是作为 Rails 4 中内置的,不要忘记将角色添加到控制器的允许列表中

class ApplicationController < ActionController::Base
  before_filter :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) |u| u.permit(:email, :password, :password_confirmation, roles: [])
  end
end

请参阅设计文档中有关强参数的部分。

您可以在视图中使用复选框来设置这些角色。

<% for role in User::ROLES %>
  <%= check_box_tag "user[roles][#role]", role, @user.roles.include?(role), :name => "user[roles][]"%>
  <%= label_tag "user_roles_#role", role.humanize %><br />
<% end %>
<%= hidden_field_tag "user[roles][]", "" %>

最后,您可以在 Ability 类中添加一种方便的方法来检查用户的角色。

# in models/user.rb
def is?(role)
  roles.include?(role.to_s)
end

# in models/ability.rb
can :manage, :all if user.is? :admin

有关限制哪些用户可以将角色分配给其他用户的方法,请参阅自定义操作。

此功能也被提取到一个名为 role_model 的小 gem(代码和操作方法)中。

如果您不喜欢此位掩码解决方案,请参阅单独的角色模型以了解处理此问题的替代方法。

【讨论】:

以上是关于导轨 4 |使用位掩码在表单中为用户分配角色 |榜样的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中为 SpriteKit 定义类别位掩码枚举?

Meteor:如何在注册过程中为用户分配不同的角色

带有十进制数的 OAuth 2 范围以使用按位掩码

通过权限位掩码从 MySQL 数据库中选择用户?

无法应用位掩码

SpriteKit 碰撞检测不起作用