Rolify: проверка ролей со сложной функциональностью внутри модели User

Я потратил четыре дня, пытаясь добиться этой роли, но безуспешно, и я не знаю, есть ли в настоящее время какой-либо способ сделать это с помощью rolify. Вот простой пример ситуации, которую я имею:

Предположим, у меня есть 3 типа ролей:

  • админ
  • разработчик
  • гость

Пользователь может быть как администратором, так и разработчиком, но не может быть и гостем.

Гость не может быть ни администратором, ни разработчиком.

Я хочу, чтобы пользователь мог устанавливать свои роли при регистрации пользователя, поэтому мне нужно проверить это поведение до того, как пользователь будет создан, и, если оно недопустимо, регистрация должна завершиться сбоем, и ни один пользователь не должен быть создан.

Я прочитал много руководств, пытающихся достичь аналогичных результатов, по крайней мере, при отправке формы, но нет объяснения этому типу проверки.

Заранее спасибо!

ОБНОВЛЕНИЕ: Я искал несколько способов реализовать это, и это направление мысли, которое у меня было в это время борьбы.

Во-первых: получите роли, выбранные в качестве входных данных, и создайте виртуальный атрибут в пользовательской модели, соответствующей этим ролям, чтобы параметры выглядели так (упрощенно)

: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

Третье: если запись проходит все проверки, создайте пользователя, а затем назначьте роли внутри регистраций # новое действие

Я думаю, что этот метод будет работать, но у меня сейчас есть некоторые проблемы с виртуальным атрибутом, и он заключается в том, что он не связан с параметрами ролей, получаемых из формы. Полагаю, я до сих пор не понимаю, как работают виртуальные атрибуты, поэтому я бы хотел, чтобы кто-нибудь объяснил мне этот вопрос.

1 ответ

Решение

Я понял! Процесс, который я добавил в обновлении, является правильным, поэтому я сделаю краткое руководство о том, как этого добиться правильно.

Цель: проверить сложную функциональность для rolify внутри пользовательской модели. Это должно быть сделано внутри модели User, потому что нужно проверять все добавляемые роли, а не каждую в отдельности.

Шаг первый: если роли, которые будет использовать ваше приложение, являются статическими, то сначала необходимо заполнить таблицу ролей конкретными ролями. Для этого я оставлю пост с другим вопросом здесь, в Переполнении стека, который подробно объясняет этот процесс:

Определение ролей с помощью 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: [])

Если вы не используете devise:

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

Шаг четвертый: Хорошо, теперь input_roles Param передается в наш User модель. Но теперь нам нужно найти способ проверки значений внутри. Поскольку этот параметр не является частью нашей модели User, мы должны создать виртуальный атрибут, чтобы иметь возможность работать с этими параметрами. Таким образом, мы просто называем его так же, как параметр, передаваемый модели:

Class User < ApplicationRecord
rolify
attr_accessor :input_roles

Теперь, когда вы хотите получить доступ к значениям, которые пользователь выбрал в качестве ролей, вам просто нужно сделать это в вашей пользовательской модели:

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

Теперь вы можете сделать все виды проверки с этой информацией! Надеюсь это поможет! Если кто-нибудь знает более чистый способ сделать это, пожалуйста, дайте мне знать. Я просмотрел все, на что мог наткнуться, и ответа не было. По крайней мере с этим проверки выполняются внутри модели, а не контроллера.

Другие вопросы по тегам