【问题标题】:Rails 5 - Rolify - trying to remove an instance of a role from a userRails 5 - Rolify - 尝试从用户中删除角色的实例
【发布时间】:2017-04-09 08:20:43
【问题描述】:

我正在尝试学习如何在我的 Rails 5 应用中使用 rolify。

我之前问过很多关于 Rolify 的问题,最近一次是here,但我一直没能找到帮助。

我正在努力弄清楚如何从用户那里删除分配的角色。

我的架构中的表有 app_roles(这是我的 CRUD,用于制作可以单独分配给用户的角色)、用户、角色和 user_roles - 如:

create_table "app_roles", force: :cascade do |t|
    t.string   "title"
    t.string   "display_name"
    t.integer  "category"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
  end

  create_table "users", force: :cascade do |t|
    t.string   "first_name"
    t.string   "last_name"
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet     "current_sign_in_ip"
    t.inet     "last_sign_in_ip"
    t.string   "confirmation_token"
    t.datetime "confirmed_at"
    t.datetime "confirmation_sent_at"
    t.string   "unconfirmed_email"
    t.integer  "failed_attempts",        default: 0,  null: false
    t.string   "unlock_token"
    t.datetime "locked_at"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.integer  "organisation_id"
    t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
    t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
    t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true, using: :btree
  end

  create_table "users_roles", id: false, force: :cascade do |t|
    t.integer "user_id"
    t.integer "role_id"
    t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id", using: :btree
  end

create_table "roles", force: :cascade do |t|
    t.string   "name"
    t.string   "resource_type"
    t.integer  "resource_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.index ["name", "resource_type", "resource_id"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree
    t.index ["name"], name: "index_roles_on_name", using: :btree
  end

这些关联是:

用户

rolify strict: true # strict means you get true only on a role that you manually add
  attr_accessor :current_role

角色

has_and_belongs_to_many :users, :join_table => :users_roles

  belongs_to :resource,
             :polymorphic => true,
             :optional => true

应用角色(没有关联 - 这是我用来通过表单创建新角色的 CRUD)

我的用户模型有:

class User < ApplicationRecord
  rolify strict: true # strict means you get true only on a role that you manually add
  attr_accessor :current_role

我无法弄清楚如何仅使用 rolify 来分配角色,就像它在 wiki 中显示的那样。这就是为什么我制作了一个单独的资源。这称为分配角色。我有一个 assign_roles_controller.rb 有:

class Users::AssignRolesController < ApplicationController

  before_action :authenticate_user!

  def index
      @app_roles = AppRole.all
  end


  def create
    user = User.find(params[:users])
    role = AppRole.find(params[:roles])
    organisation = Organisation.find(current_user.organisation)
     # byebug

    user.add_role role.display_name, organisation

    flash[:notice] = "Successfully created"
    redirect_to action: :index
  end

  def show
    @users = User.all
  end

  def update
  end

  def destroy

    # user = User.find(params[:users])
    # user = User.find(params[:id])
    user = User.find_by_id(params[:id])
    # User.find(params[:id])
    # role = AppRole.find(params[:roles])
    role = params[:user][:roles]
    # assigned_role = user.roles
    # user_roles = user.roles
    # organisation = Organisation.first
    organisation = Organisation.find(current_user.organisation)

    # byebug

    user.remove_role role.display_name, organisation

    flash[:notice] = "Successfully created"
    redirect_to root_path
  end

end

路由是嵌套的,所以我有:

resources :users, shallow: true do
    scope module: :users do
      resources :assign_roles

在我的用户索引中,我试图显示一个用户列表,其中包含他们的每个角色和一个删除角色链接。在 users/index.html.erb 中,我有:

<% user.roles.each do |role| %>
              <table class="table table-bordered">
              <tr>
                <td><%= role.name.titleize %></td>
                <td><%= link_to 'Remove role', assign_role_path(user.roles),  method: :delete, data: { confirm: 'Are you sure?' } %></td>
              </tr>
              </table>
             <% end %>

在控制台中,我可以这样做:

Organisation.find_roles(nil, User.find_by(organisation_id:1))
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."organisation_id" = $1 LIMIT $2  [["organisation_id", 1], ["LIMIT", 1]]
  Role Load (0.7ms)  SELECT "roles".* FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (resource_type IN ('Organisation'))  [["user_id", 43]]
 => #<ActiveRecord::AssociationRelation [#<Role id: 3, name: "asdf", resource_type: "Organisation", resource_id: 1, created_at: "2016-10-24 23:00:40", updated_at: "2016-10-24 23:00:40">, #<Role id: 4, name: "ffff", resource_type: "Organisation", resource_id: 1, created_at: "2016-11-09 00:26:56", updated_at: "2016-11-09 00:26:56">]> 

用户有 2 个角色。

当我尝试删除其中一个时,我收到一条错误消息:

undefined method `[]' for nil:NilClass

该错误在我的分配角色控制器的销毁操作中抱怨此公式(这是某人对另一个 SO 帖子的建议的副本):

role = params[:user][:roles]

当我尝试销毁操作时:

def destroy
    user = User.find_by_id(params[:id])
    assigned_role = user.roles
    organisation = Organisation.find(current_user.organisation)

    # byebug

    user.remove_role assigned_role.display_name, organisation

    flash[:notice] = "Successfully created"
    redirect_to root_path
  end

然后我收到一条错误消息:

undefined method `roles' for nil:NilClass

我认为该错误可能与我试图从用户中删除一个角色有关,但我使用复数来查找所有角色。我不确定如何找到我在使用索引中引用的特定角色。

谁能帮我解决这个问题?

【问题讨论】:

  • 只需使用 rolify 就可以删除 user.remove_role :admin
  • 否 - 我使用的是作用域角色。这不适用于作用域角色。这是针对全球角色的。无论如何,谢谢 - 但这不是我需要的。
  • 一个问题,在您的link_to 'Remove role' 中您不应该使用role 而不是user.roles
  • @Andrés - 我试过仔细检查 - 但不,那不起作用。此外,这对我来说没有意义,因为我试图删除角色和用户之间的关联(而不是角色本身)。该错误当前引用了上面的行 (user_roles = user.role) 或 (assign_role = user.roles) - 我一直在为这一行尝试各种形式的表达,但找不到有效的表达方式。
  • destroy方法中,首先检查用户是否存在,然后再尝试访问roles方法。也许user 不存在或者只是数据库无法访问资源。错误 undefined method roles' for nil:NilClass` 这是因为 User.find 什么也没找到

标签: ruby-on-rails ruby associations rolify


【解决方案1】:

请参考一次。

 def destroy
    user = User.find_by_id(params[:id])
    assigned_role = user.role_name
    organisation = Organisation.find(current_user.organisation)

    # byebug

    user.remove_role assigned_role, organisation

    flash[:notice] = "Successfully created"
    redirect_to root_path
  end

【讨论】:

  • 嗨阿图尔。谢谢你的建议。它不起作用。原因是我在任何地方都没有任何名为“role_name”的东西,这是您建议我在分配的角色变量中使用的。无论如何,非常感谢你试图帮助我。我已经尝试了数百次猜测,但没有什么可以尝试的。
  • 嗨,医学。你能告诉我你在使用 Rolify gem 吗?
  • 能否请您从控制台尝试一次。
  • 您建议我在控制台中尝试做什么?我上面的帖子概述了用户拥有的相关角色 - 我从控制台生成了该 sql。您是否想过在控制台中尝试什么?
  • 请检查关联。您有存储创建角色的 AppRoles 表。您在需要放置 app_role_id 而不是 role_id 的地方生成迁移 users_roles。请看上面的表格。如果我有任何问题,请纠正我。
【解决方案2】:

我在 codementor 上进行了一次会议,终于得到了答案。

答案是:

def destroy
#/assign_roles/9?user_id=27
    user = User.find_by_id(params[:user_id])
    assigned_role = Role.find(params[:id])
    organisation = Organisation.find(current_user.organisation)

    user.remove_role assigned_role.name.to_sym, current_user.organisation #user.organisation

    flash[:notice] = "role deleted"
    redirect_to root_path
  end

在视图中:

        <td><%= link_to 'Remove role', assign_role_path(role, user_id: user),  method: :delete, data: { confirm: 'Are you sure?' } %></td>

具体问题是角色名称需要先转换为字符串才能删除,并且用户 find 方法是在最近的资源中搜索(这意味着它是在角色模型中查找 id,而不是用户模型。这意味着 id 将无法返回用户 id。我不理解这部分 rails 的搜索结构 - 所以我不得不把它当作给定的(不理解它),但很高兴,多年后试图解决这个问题,我可以继续。

【讨论】:

    猜你喜欢
    • 2017-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多