【问题标题】:Rails 5: check if role ID belongs to user belonging to current_user (through association)Rails 5:检查角色ID是否属于属于current_user的用户(通过关联)
【发布时间】:2016-10-11 20:09:34
【问题描述】:

在我的 controllers/common/roles_controller.rb 中,我想检查特定角色 (ID) 是否属于 current_user 公司用户,如果不属于,则重定向到 errors_path

def correct_role
  role_user = Role.where(:id => params[:id]).select('user_id').first
  company_user = current_user.companies.includes(:users)
  redirect_to(errors_path) unless company_user.include? role_user.id
end

定义:

  • role_user - 查找特定角色 ID 的用户 ID(“user_id”是角色表的列)
  • company_user - 查找属于公司的所有用户 ID,属于 current_user

models/role.rb

belongs_to :user, optional: true, inverse_of: :roles
accepts_nested_attributes_for :user

enum general: { seller: 1, buyer: 2, seller_buyer: 3}, _suffix: true
enum dashboard: { denied: 0, viewer: 1, editer: 2, creater: 3, deleter: 4}, _suffix: true

models/user.rb

#User has roles
  has_many :roles
  accepts_nested_attributes_for :roles, reject_if: proc { |attributes| attributes[:name].blank? }

  # User has many companies
  has_many :accounts, dependent: :destroy
  has_many :companies, through: :accounts

models/account.rb

class Account < ApplicationRecord
  belongs_to :company
  belongs_to :user
  accepts_nested_attributes_for :company, :user
end

models/company.rb

has_many :accounts, dependent: :destroy
has_many :users, through: :accounts

目前role_usercompany_user 我可以找到这两个ID,但是我无法进行检查。请问我该如何正确地做到这一点?感谢您的帮助!

更新

@sajan 代码在我打开 /common/roles/1/edit 时在控制台中给出这个(current_user ID=1 并且应该被允许编辑):

Parameters: {"id"=>"1"}
User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
(0.6ms)  SELECT COUNT(*) FROM "companies" INNER JOIN "accounts" ON "companies"."id" = "accounts"."company_id" WHERE "accounts"."user_id" = ?  [["user_id", 1]]
(0.3ms)  SELECT "roles".id FROM "roles" WHERE "roles"."user_id" = ?  [["user_id", 1]]

@Abhishek Kumar 控制台中的代码给出:

Parameters: {"id"=>"1"}
    User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
    Company Load (0.5ms)  SELECT "companies".* FROM "companies" INNER JOIN "accounts" ON "companies"."id" = "accounts"."company_id" WHERE "accounts"."user_id" = ?  [["user_id", 1]]
    (0.4ms)  SELECT "users".id FROM "users" INNER JOIN "accounts" ON "users"."id" = "accounts"."user_id" WHERE "accounts"."company_id" = ?  [["company_id", 13]]
    Role Load (0.2ms)  SELECT  "roles"."user_id" FROM "roles" WHERE "roles"."id" = ? ORDER BY "roles"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]

更新 v2

所以我正在尝试使用此代码:

def correct_role
company_user_ids = current_user.companies.map(&:user_ids)
role_user = Role.where(:id => params[:id]).select('user_id').first
unless role_user.user_id.in?(company_user_ids)
redirect_to(errors_path)
end
end

无论如何它都会重定向到errors_path,这就是我在控制台中的:

Parameters: {"id"=>"1"}
User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
Company Load (0.5ms)  SELECT "companies".* FROM "companies" INNER JOIN "accounts" ON "companies"."id" = "accounts"."company_id" WHERE "accounts"."user_id" = ?  [["user_id", 1]]
(0.4ms)  SELECT "users".id FROM "users" INNER JOIN "accounts" ON "users"."id" = "accounts"."user_id" WHERE "accounts"."company_id" = ?  [["company_id", 13]]
Role Load (0.3ms)  SELECT  "roles"."user_id" FROM "roles" WHERE "roles"."id" = ? ORDER BY "roles"."id" ASC LIMIT ?  [["id", 1], ["LIMIT", 1]]

【问题讨论】:

    标签: ruby-on-rails arrays ruby


    【解决方案1】:

    似乎更好的逻辑是在 current_user 的模型上定义通过公司和用户到角色的关联。

    然后你可以检查:

    def correct_role
      redirect_to(errors_path) unless current_user.company_user_roles.where(id: params[:id]).exists?
    end
    

    这将是一个单独的 SQL 语句,将返回 0 行或 1 行,并在适当的索引到位的情况下非常快速地执行。

    编辑:

    在 company.rb 中添加:

    has_many :user_roles, through: :users, source: :roles
    

    在 user.rb 中(假设 current_user 是这个模型的一个实例)添加:

    has_many :company_user_roles, through: :companies, source: :user_roles
    

    【讨论】:

    • 感谢您的建议。我在上面添加了公司模型。请你举个例子,模型应该是什么样子?我是个初学者:)
    • 谢谢,看来它正在工作 :) 非常感谢您救了我。 Rails 社区震撼!
    • 没问题——如果某些事情看起来很复杂,那可能是做错了;)
    • 是的,没错!你的代码就像魅力一样,再次感谢;)
    【解决方案2】:

    也许你可以这样做:

    def correct_role
      unless current_user.companies.count > 0 && current_user.role_ids.include?(params[:id])
        redirect_to(errors_path)
      end
    end
    

    【讨论】:

    • 谢谢,但是我收到语法错误:意外的 tIDENTIFIER 期望关键字_end
    • 现在试试编辑后的答案,我删除了一个空格。并且错误正在发生,因为您错过了关闭带有end 行的块。检查一下。
    • 似乎已经接近了,但还没有 - 请你检查一下更新中上面给我的控制台是什么?
    • 那么问题是什么?它是否重定向到 errors_path ?如果是这种情况,请检查您是否拥有user_id = 1 的角色。和current_user 至少有 1 家公司
    • 是的,它的错误。 current_user 的 ID=1 并且在角色表列中 user_id = 1 例如,current_user 有两个要编辑的角色 (1, 3) 因为有两个用户属于公司,其中角色表中 user_id = (1, 3)
    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    相关资源
    最近更新 更多