我正在开发一个Ruby on Rails应用程序,它有两种"角色"。
它们都相似,因为它们只有name
列。前者将与CanCanCan等授权工具一起使用。我目前计划允许用户和角色使用has_many :through
关系来支持其他许多人。
class Role
has_many :user_roles
has_many :users, through: :user_roles
end
class User
has_many :user_roles
has_many :roles, through: :user_roles
end
class UserRole
belongs_to :user
belongs_to :role
end
我的问题是:
我计划使用术语"角色"在后者的用户界面中,显示了什么"角色"用户有。前者我想更多的是他们在应用程序中拥有什么特权。
答案 0 :(得分:2)
如果你离开角色和身份验证的技术方面,并尝试用更加面向业务的方法来描述“事物”,那么你就可以让自己更加清晰。
我的理解是:您对应用程序的用户有一个定义,用于描述该用户具有的授权,例如: “管理员”拥有的权利多于“编辑”或“社区管理者”。
您还希望应用程序的这些用户能够创建与(其他?)用户关联的名称。正如我所理解的,这些名称与授权无关。 也许这些名称更像是标签,人们可以分配? 我会将两者分开,因为它不应该让用户创建角色或修改现有角色,这可以授予他们访问管理功能的权限。
如果你想看一个标记宝石,我可以推荐这个:https://github.com/mbleigh/acts-as-taggable-on我用了好几年了,虽然有它的缺点,但它很可靠。
答案 1 :(得分:1)
我建议在推出自己的解决方案之前先看一下rolify,因为它会解决你以后需要重新实现/发现的一些事情(例如角色查询,避免N + 1查询等) )。它还与can?
很好地集成,并且应该适用于您的问题的授权部分。
虽然允许用户创建新角色并不是不可能的(通过在Role.create
之上投掷输入表单),但这开始变得混乱,因为您需要跟踪哪些用于授权以及哪些用于提供信息(和用户创建)。
由于这两组事物是出于不同的目的,我完全同意this other answer分离用户生成的实体更清晰,并希望将它们实现为标记。您可以在某些视图中一起显示所有“角色”,但这并不意味着将它们存储在单个表中是有意义的。
旁注:如果您最终推出自己的解决方案,请考虑在此处使用HABTM。仍将创建连接表,但您不必管理连接表模型。 E.g。
has_and_belongs_to_many :users, join_table: :users_roles
答案 2 :(得分:0)
由于您只有有限数量的角色,因此可以使用位掩码并将其直接存储在用户模型上作为简单整数。
有关详细信息,请参阅此Railscasts。这将是最有效的数据库和关联方式,尽管这可能不是最简单的理解。唯一真正的限制是你不能改变你检查的值数组,只能附加到它。
祝你好运!答案 3 :(得分:0)
我会创建另一个模型Permission,您可以在其中创建要在任何给定角色下管理的所有权限的列表。
然后在权限和角色之间有多对多。
从UserRole实例,您将能够列出权限,并且将来您可以为角色添加其他权限,只需在几个表中运行插入
角色:Onwer,厨师,厨师,服务员 权限:can_cook,can_buy_wine,can_manage,can_charge_custome
所有者:can_manage,can_buy_wine,can_charge_customer 厨师:can_cook,can_manage 服务员:can_charge_customer
这将是一个良好的开端,您可以根据自己的需求将角色功能发展为没有外部依赖关系。
答案 4 :(得分:0)
此外,您可以只使用Users
表并将role
列添加为整数,并为它们提供默认0整数的角色代码。
#app/helpers/roles_helper.rb
module RolesHelper
@roles = {
'Default' => 0,
'Waiter' => 10,
'Chef' => 20,
'Superadmin' => 30
}
class << self
def list_roles
@roles.map{|k,v| [k,v] }
end
def code(str)
return @roles[str]
end
def value(id)
return @roles.key(id)
end
end
def require_default_users
unless current_user && current_user.role >= RolesHelper.code('Waiter')
redirect_to root_url(host: request.domain)
end
end
def require_superadmin_users
unless current_user && current_user.role >= RolesHelper.code('Superadmin')
redirect_to courses_path
end
end
end
样品:
class Admin::AdminController < ApplicationController
include RolesHelper
def sample_action_method
require_default_users #if non admin user redirect ...
puts "All Roles: #{RolesHelper.list_roles}"
puts "Value: #{RolesHelper.value(30)}"
puts "Code: #{RolesHelper.code('Superuser')}"
end
end