Rolify:在用户模型中验证具有复杂功能的角色 [英] Rolify: Validate roles with complex functionality inside the User model

查看:287
本文介绍了Rolify:在用户模型中验证具有复杂功能的角色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我花了四天的时间尝试实现这个角色验证,没有成功,我不知道目前是否有任何方法来执行此行为与rolify。以下是我遇到的一个简单的例子:



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




  • admin

  • 开发人员

  • 客人



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



客人不能是管理员或开发人员。 p>

我希望用户能够在用户注册时设置角色,所以我需要在用户创建之前验证此行为,如果无效,注册应该失败,没有用户应该被创建。



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



提前感谢!



更新:
我一直在寻找一些实现这一点的方法,这是我在这次斗争中遇到的思路。



首先:接收所选择的角色作为输入,并在与此角色对应的用户模型中创建一个虚拟属性,以使参数看起来像这样(简化的)

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

如果所有角色都被选中,和

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

如果没有选择角色。



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

 类用户< ApplicationRecord 
attr_accessor:roles
validate:roles_valid

def roles_valid
#定义自定义验证
end
end
如果记录通过所有验证,创建用户,然后在注册中分配角色#新的动作



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

解决方案

我现在得到了我在更新中添加的过程是正确的,所以我将简要介绍如何正确地实现这一点。



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



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



使用Rolify定义角色



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

 <%= form_for(resource,as:resource_name,url:registration_path(resource_name) )do | f | %GT; 
<! - 在此添加您的注册输入 - >
<%Role.all.each do | role | %GT;
<%= f.checkbox:input_roles,{multiple:true},role.name,nil%>
<%= role.name%>
<%end%>
<%end%>

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

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

重要说明!如果用户没有选择任何角色,那么varialbe input_roles 将不会被定义!您必须在验证中检查。 此外,不要更改变更名称 角色,我犯了这个错误,并通过地狱试图修复我得到的所有错误。如果有兴趣看到我经历的一切,这里是我创建的问题的链接:



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



步骤三:由于您要为表单添加新参数,还必须将其包含在强参数中。因为这个变量是一个数组,所以你必须在你强有力的参数中明确定义这个参数:



如果你使用Devise:

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

如果您不使用设计:

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

第四步:好的,现在, input_roles param正在传入我们的用户模型。但是,现在我们需要找到一种验证内部值的方法。由于此参数不属于我们的用户模型,因此我们必须创建一个虚拟属性才能使用此参数。所以我们把它命名为与传递给模型的参数相同,如下所示:

 类用户< ApplicationRecord 
rolify
attr_accessor:input_roles

现在当你想访问值用户已经选择作为角色,您只需在此处执行此操作。用户模型:

  self.input_roles.to_a#=> ; [admin,开发者,客人]如果用户选择所有角色

现在你可以使用这些信息进行各种验证!希望这可以帮助!
如果有人知道一个更干净的方法来做,请让我知道。我看着我可以绊倒的一切,没有回答。在这样做的时候,验证是在模型中完成的,而不是控制器。


I've spent four days trying to achieve this role validation with no success, and I don't know if there is currently any way to do this behaviour with rolify. Here's a simple example of the situation I am having:

Suppose I have 3 types of roles:

  • admin
  • developer
  • guest

A user can be both an admin and a developer, but cannot be also a guest.

A guest cannot be either an admin nor a developer.

I want the user to be able to set their roles on user registration, so I need to validate this behaviour before the user is created, and if it is not valid, the registration should fail and no user should be created.

I've read a lot of guides trying to achieve similar results, at least for the form submission, but there is no explanation about this type of validation.

Thanks in advance!

UPDATE: I've been searching for some ways to implement this, and this is the line of thought I've had during this time of struggles.

First: receive the roles selected as input and create a virtual attribute at the user model corresponding to this roles so that the params would look like this (simplified)

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

if all roles are selected, and

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

if no role is selected.

Second: Do any type of validations with this virtual attribute(simplified)

Class User < ApplicationRecord
  attr_accessor :roles
  validate :roles_valid

  def roles_valid
    # Define custom validation
  end
end

Third: if the record passes all the validations, create user and then assign the roles inside the registrations#new action

I think this method would work, but I am now having some problems with the virtual attribute, and it is that it doesn't seem to be connected to the roles params being received from the form. I guess I still don't understand how virtual attributes work, so I wish someone would clear me out on this one.

解决方案

I got it now! The process I added in the update is correct, so I will make a brief guide on how to achieve this correctly.

Objective: validate complex functionality for rolify inside the User model. This must be done inside the User model because one must check all the roles being added, and not each individually

Step One: If the roles your app is going to use are static, then you must first populate your roles table with the specific roles. For this, I will leave a post from another question here in Stack Overflow that explains this process in depth:

Defining Roles with Rolify

Step two: modify your registration form. In order to get the roles the user has chosen, we must first add some checkboxes corresponding to the roles defined on step one. Here is a simple code for this.

<%= 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 %>

Doing this will generate all the checkboxes necessary, and store the result inside the variable

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

Important notes! if the user does not select any role, then the varialbe input_roles won't be defined! you must check for this in your validations. ALSO, DO NOT CHANGE THE NAME OF THE VARIABLE TO roles, I made this mistake and went through hell trying to fix all the errors I was getting. If interested on seeing everything I went through, here is a link to the issue I created:

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

Step three: Since you are adding a new parameter to the form, you must also include it inside your strong parameters. Since this variable is an array, you must explicitly define this inside your strong parameters:

In case you are using Devise:

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

In case you aren't using devise:

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

Step four: Ok, so now the input_roles param is being passed into our User model. But, now we need to find a way to validate the values inside. Since this parameter is not part of our User model, we must create a virtual attribute to be able to work with this parameters. So we just name it the same as the param being passed to the model, like this:

Class User < ApplicationRecord
rolify
attr_accessor :input_roles

Now when you want to access the values the user has selected as roles, you just have to do this in you User model:

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

Now you can do all sorts of validation with this information! Hope this helps! If anyone know of a cleaner way to do this, please let me know. I looked through everything I could stumble upon and no answer was given. At leaast with this the validations are done inside the model, instead of the controller.

这篇关于Rolify:在用户模型中验证具有复杂功能的角色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆