Rails 5:检查角色ID是否属于属于current_user的用户(通过关联)

时间:2016-10-11 08:05:40

标签: ruby-on-rails arrays ruby

在我的 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

模型/ 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

模型/ 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

模型/ account.rb

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

模型/ 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]]

2 个答案:

答案 0 :(得分:1)

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

然后你可以检查:

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

这将是一个返回零行或一行的SQL语句,并且可以使用适当的索引快速执行。

编辑:

到company.rb,添加:

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

to user.rb(假设current_user是此模型的一个实例)add:

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

答案 1 :(得分:0)

也许你可以这样做:

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