在我的 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_user
和company_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]]
答案 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