#ruby-on-rails #authorization #ruby-on-rails-6 #cancancan #ruby-on-rails-6.1
Вопрос:
У меня есть таблица пользователей (созданная devise), я добавил столбец ролей, который может быть: администратор, менеджер и агент. И в user.rb я поместил ПЕРЕЧИСЛЕНИЕ вот так:
class User < ApplicationRecord
enum role: { admin: 0, manager: 1, agent: 2 }
end
Я использую канканкан и хотел бы сделать 2 вещи:
1 — Как отобразить меню или другую кнопку в соответствии с ролью зарегистрированного пользователя? На мой взгляд, я сформулировал это так:
<% if current.present? amp;amp; current_user.admin? %>
<%= link_to 'Purchases (Admin access)', admin_purchases_path, class: 'nav-link mr-5 ' %>
<% end %>
2 — Как отобразить конкретную страницу в соответствии с ролью пользователя? В моем User.rb я поместил это:
def admin?
self.role == 'admin'
end
Я пробую это на способности.рб:
user ||= User.new # guest user (not logged in)
if admin?
can :manage, :all
else
can :read, :all
end
И на контроллерах я поставил:
load_and_authorize_resource
Но я получаю ошибку:
NoMethodError in Home#index
undefined method `admin?' for nil:NilClass
<% if current_user.admin? %> <<< On this line here
Комментарии:
1. я думаю, что у вас здесь опечатка
<% if current.present? amp;amp; current_user.admin? %>
Ответ №1:
Вы можете использовать оператор безопасной навигации, чтобы избежать нулевой ошибки:
<% if current_useramp;.admin? %>
Однако это все еще несколько противоречит образцу. Весь смысл использования библиотеки авторизации, такой как CanCanCan, состоит в том, чтобы консолидировать логику авторизации, а не распространять ее на все ваши контроллеры и представления.
Вместо этого вам следует спросить CanCanCan, имеет ли пользователь право делать то, что делает ссылка:
<% if can? :administrate, :purchases %>
<%= link_to 'Purchases (Admin access)', admin_purchases_path, class: 'nav-link mr-5 ' %>
<% end %>
Ему не обязательно знать, является ли пользователь администратором или что администраторам разрешено администрировать покупки. Это работа канканцев.
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
can :administrate, :all
else
can :read, :all
end
В моем User.rb я поместил это ..
Этот код полностью повторяется. enum role: { admin: 0, manager: 1, agent: 2 }
уже создает методы admin?
взаимодействия , manager?
и agent?
.
Проблема в ability.rb
том, что вы звоните if admin?
, фактически не указывая получателя. Ты должен был позвонить if user.admin?
.