但是,我不知道如何继续我创建的系统.我正在开发一个系统,用户有很多角色.所以这不是一个简单的,因为有一个用户的状态从未确认到确认,然后可能到管理员.
用户现在有许多角色,可以是潜在的,骑自行车的人,协调者,管理员,论坛管理员,商店管理员,超级管理员和筹款人.
所以层次结构如下所示:
superadmin
forum admin,store admin
cyclist,coordinator,manger,fundraiser
potential
但是,一个状态机在这里不会被切断,因为一个用户完全可以同时拥有所有上述角色.
我正在实现我自己的类方法,这样可以有点模仿状态机:
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
这只是一个骗子.所以我的问题是:
我做错了吗?如何处理多角色的用户?
2)即使我做的正确,我想创建一个state_machine类的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?准备打包成为我的第一个宝石?
我不知道如何动态创建方法,但我想开始:)
只是一个想法,也许多轮方法可以通过Roles.all动态获取所有角色,并自动添加上述方法!也许甚至照顾has_many:jobs has_many:roles,通过::jobs
此外,我应该如何验证这些角色?我正在控制器中的前一个块中执行此操作:
def only_superadmins redirect_to root_url if !current_user.has_role?('superadmin') end
我的应用程序控制器中也有一些这些方法,只有_superadmins,only_cyclists等等,我们通过before_method方法在各种子控制器中调用它们.
这样好吗我应该使用cancan还是什么东西?
如果我做的正确,我想知道我应该如何动态地创建这些方法与我的宝石.我在想这些事情:
class panel_controller < ApplicationController allowed_roles [:super_admin,:store_admin] end
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
虽然我不明白为什么不起作用,但这并没有使我效率太高.
也许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
我只想要一些指针真的:)
如何创建一个gem以使allow_roles方法可用于用户模型可用的控制器和多重卷?
Cancan can can manage multiple roles like this?我应该用这个吗
解决方法
为了处理模型的角色,一个很好的选择是使用gem rolify.通过它,您可以轻松地定义所需的角色,并将所需的角色与您的用户相关联.使用简单,只需按照官方文档here.
CanCan(或其附件CanCanCan)用于处理权限.您将定义每个角色(由rolify定义)的用户有权在文件app / models / ability.rb中执行的操作.然后,在控制器或视图中,您只需验证用户是否有权对资源执行操作.例如,在您的控制器中,您可以验证像@comment = Comment.new(params)这样的授权;授权! :创建@comment,并在您的视图中验证授权,如果可以的话? :创建,评论.请注意07004的官方文档,了解如何设置和使用CanCan.
围绕这些您的具体问题:
宝石添加Rolify(宝石“rolify”)和CanCan(宝石“cancan”)宝石.
执行rails shell命令rails g rolify Role User创建一个名为Role的新类(或使用您喜欢的名称),并在现有类User中添加一些类方法.由于新的角色角色将向您的数据库添加表格角色,因此必须运行rake db:migrate(使用ActiveRecord时).
class Forum < ActiveRecord::Base resourcify end
完成这些步骤后,您的User类将配备add_role,remove_role和has_role方法,您可以使用它们添加任意数量的角色:
user.add_role :superadmin user.add_role :fundraiser user.has_role? :superadmin # >> true user.has_role? :fundraiser # >> true
您甚至可以将角色定位到一个资源或实例:
user.add_role :cyclist,Forum user.add_role :coordinator,Forum.first user.has_role? :cyclist,Forum # >> true user.has_role? :cyclist,Store # >> false user.has_role? :coordinator,Forum.first # >> true user.has_role? :coordinator,Forum.second # >> false
所以你可以这样写你的User类:
class User < ActiveModel::Base rolify has_many :jobs # checking def is_superadmin? self.has_role?('superadmin') end # changing def add_new_role(role) self.update_attributes(accepted_at: Time.now) if self.is_only_potential? self.add_role(role) end def make_superadmin! add_new_role('superadmin') end def denounce_superadmin! remove_role('superadmin') end end
要认证这些角色,您可以使用CanCan.执行rails shell命令rails g cancan:生成文件app / models / ability.rb的能力,您可以在其中定义角色的权限.
class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user if user.has_role? :superadmin can :manage,All # can manage (Read,Create,Update,Destroy,...) everything elsif user.has_role? :forum_admin can :manage,Forum # can manage (Read,...) any Forum elsif user.has_role? :store_admin can :manage,Store do |store| # Can manage only its own store store.try(:user) == user end elsif user.has_role? :forum_member can :create,Post do |post| if post.forum.members.include? user true end end can :destroy,Post do |post| post.try(:user) == user end can :update,Post do |post| post.try(:user) == user end elsif ... else # Users without role can :read,All end end end
在您的控制器中,您可以致电授权!方法.例如:
# app/controllers/posts_controller.rb def create @post = Post.new(params[:post]) @post.user = current_user authorize! :create,@post if @post.save redirect_to @post else render :action => 'new' end end
或者,您可以在控制器的起始处包含这些信息,并在每个操作之前自动加载和授权资源(或不):
class PostController < ApplicationController load_and_authorize_resource :post ... def create authorize! :create,@post if @post.save redirect_to @post else render :action => 'new' end end
观看本教程RailsCast开始使用CanCan.
我希望这可以帮助您指导您解决问题.