Rolify:在User模型中验证具有复杂功能的角色

时间:2017-03-22 22:11:05

标签: ruby-on-rails forms validation devise rolify

我花了四天时间尝试完成此角色验证但没有成功,我也不知道目前是否有任何方法可以使用rolify执行此操作。这是我所处情况的一个简单例子:

假设我有3种类型的角色:

  • 管理员
  • 显影剂

用户既可以是管理员,也可以是开发者,但也不能是访客。

访客不能是管理员也不能是开发者。

我希望用户能够在用户注册时设置他们的角色,因此我需要在创建用户之前验证此行为,如果它无效,则注册失败并且不应创建任何用户。< / p>

我已经阅读了许多尝试获得类似结果的指南,至少对于表单提交,但没有关于此类验证的解释。

提前致谢!

更新 我一直在寻找实现这一目标的方法,这就是我在这段艰难时期所拥有的思路。

首先:接收选定为输入的角色,并在与此角色对应的用户模型中创建虚拟属性,以便params看起来像这样(简化)

:params => { :user => {:email, :password, :roles => ["admin", "developer", "guest"]}}

如果选择了所有角色,

:params => { :user => {:email, :password}}

如果没有选择任何角色。

第二:使用此虚拟属性进行任何类型的验证(简化)

Class User < ApplicationRecord
  attr_accessor :roles
  validate :roles_valid

  def roles_valid
    # Define custom validation
  end
end

第三:如果记录通过了所有验证,请创建用户,然后在注册中分配角色#new action

我认为这种方法可行,但我现在对虚拟属性有一些问题,并且它似乎并没有连接到从表单接收的角色参数。我想我还是不明白虚拟属性是如何工作的,所以我希望有人能在这个问题上让我知道。

1 个答案:

答案 0 :(得分:2)

我现在知道了!我在更新中添加的过程是正确的,因此我将简要介绍如何正确实现此目的。

目标:验证用户模型内部rolify的复杂功能。这必须在用户模型中完成,因为必须检查所有要添加的角色,而不是每个角色

第一步:如果您的应用将要使用的角色是静态的,那么您必须首先使用特定角色填充角色表。为此,我将在Stack Overflow中留下另一个问题的帖子,深入解释这个过程:

Defining Roles with Rolify

第二步:修改您的注册表单。为了获得用户选择的角色,我们必须首先添加一些与第一步中定义的角色相对应的复选框。这是一个简单的代码。

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <!-- ADD HERE ALL YOUR REGISTRATION INPUTS -->
  <% Role.all.each do |role| %>
    <%= f.checkbox :input_roles, {multiple: true}, role.name, nil %>
    <%= role.name %>
  <% end %>
<% end %>

执行此操作将生成所需的所有复选框,并将结果存储在变量

params => {:user => { :input_roles => [] }}

重要说明!如果用户未选择任何角色,则无法定义变量input_roles!您必须在验证中检查这一点。 另外,不要改变变量的名称 roles,我犯了这个错误,并试图解决我遇到的所有错误。如果有兴趣看到我经历的一切,这里是我创建的问题的链接:

https://github.com/RolifyCommunity/rolify/issues/446

第三步:由于您要向表单添加新参数,因此您还必须将其包含在强参数中。由于此变量是一个数组,因此必须在强参数中明确定义:

如果您使用的是Devise:

devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :password, :password_confirmation, input_roles: [])

如果您没有使用设计:

params.require(:user).permit( :email, :password, :password_confirmation, input_roles: [])

第四步:好的,现在input_roles param正在传递到我们的User模型中。但是,现在我们需要找到一种方法来验证里面的值。由于此参数不是我们的用户模型的一部分,因此我们必须创建一个虚拟属性才能使用此参数。所以我们只是将它命名为传递给模型的param,就像这样:

Class User < ApplicationRecord
rolify
attr_accessor :input_roles

现在,当您想要访问用户选择为角色的值时,您只需在用户模型中执行此操作:

self.input_roles.to_a # => ["admin", "developer", "guest"] If the user selected all roles

现在您可以使用此信息进行各种验证!希望这可以帮助! 如果有人知道更清洁的方法,请告诉我。我查看了我可以偶然发现的一切,但没有给出答案。至少与此相比,验证是在模型内完成的,而不是在控制器中完成。