我使用 state_machine 取得了巨大的成功,并且喜欢它通过几行代码动态创建的类方法。
但是,我不确定如何继续我正在创建的系统。我目前正在开发一个用户具有多种角色的系统。所以这并不像拥有一个状态来自的用户那么简单未证实 to 确认的然后有可能admin.
一个用户现在有很多角色,并且可以是潜在的, a cyclist, a 协调员, a manger, a 论坛管理员, a 商店管理员, a 超级管理员 and a 筹款活动.
所以层次结构是这样的:
超级管理员
论坛管理员, 商店管理员
cyclist, 协调员, manger, 筹款活动
潜在的
然而,一个状态机并不能解决这个问题,因为一个用户完全有可能同时拥有上述所有角色。
我正在实现我自己的类方法,如下所示,以某种程度模拟状态机:
class User < ActiveModel::Base
has_many :jobs
has_many :roles, through: :jobs
def role_array
self.roles.pluck(:role)
end
def has_role?(role)
role_array.include?(role)
end
# checking
def is_superadmin?
role_array.include?('superadmin')
end
# changing
def add_role(role)
self.update_attributes(accepted_at: Time.now) if self.is_only_potential?
self.user_roles.create(role_id: Role.find_by(role: role).id ) if !self.has_role?(role)
end
def remove_role(role)
self.user_roles.find_by( role_id: Role.find_by(role: role).id ).destroy if self.has_role?(role)
end
def make_superadmin!
add_role('superadmin')
end
def denounce_superadmin!
remove_role('superadmin')
end
end
这只是有点无聊。所以我的问题是:
1)我做对了吗?您将如何处理具有多个角色的用户?
2)即使我做对了,我也想创建一个 state_machine-esque DSL,所以当我需要创建一个新角色时,比如说“跑步者”,我可以在我的模型中做这样的事情:
class User < ActiveModel::Base
has_many :jobs
has_many :roles, through: :jobs
multiroles initial: :potential do
roles [:superadmin, :forum_admin, :store_admin, :cyclist, :coordinator, :manager, :fundraiser, :potential]
# dynamically creates the above methods for getting and setting for all roles
end
我应该如何创建多角色方法?里面lib
?准备好作为我的第一颗宝石打包了吗?
我不知道如何动态创建方法,但我想开始:)
只是一个想法,也许multiroles
方法可以动态获取所有角色Roles.all
并自动添加以上方法!也许甚至会照顾has_many :jobs
has_many :roles, through: :jobs
另外,我应该如何验证这些角色?我目前正在控制器的 before 块中执行此操作:
def only_superadmins
redirect_to root_url if !current_user.has_role?('superadmin')
end
我的应用程序控制器中也有很多这些方法,only_superadmins
, only_cyclists
等,我通过以下方式给他们打电话before_method
各种子控制器中的方法。
这个可以吗?我应该使用康康舞还是其他什么?
如果我做得正确,我想知道应该如何使用我的 Gem 动态创建这些方法。我正在思考以下几点:
class panel_controller < ApplicationController
allowed_roles [:super_admin, :forum_admin, :store_admin]
end
allowed_roles 方法将创建这些方法
def allowed_roles(role_array)
role_array.each do |role|
define "only_#{role.to_s}s" do |arg|
redirect_to root_url if !current_user.has_role?(arg.to_s)
end
end
end
这样就会以编程方式创建这些方法:
def only_super_admins
redirect_to root_url if !current_user.has_role?('super_admin')
end
def only_forum_admins
redirect_to root_url if !current_user.has_role?('forum_admin')
end
def only_store_admins
redirect_to root_url if !current_user.has_role?('store_admin')
end
虽然我不明白为什么这行不通,但我觉得这并不算太有效。
Maybe allowed_roles
应该看起来像这样:
def allowed_roles(wanted_roles)
redirect_to root_url unless (current_user.role_array & wanted_roles).empty? # it's ONLY empty when any of the current_user roles exists in the wanted_roles array
end
我真的只是想要一些指示:)
我如何创建宝石来制作allowed_roles
控制器可用的方法和multiroles
可供用户使用的模型?
Can cancan
像这样管理多个角色?我应该只用那个吗?