2016-09-26 17 views
0

感谢您的阅读!在我的应用中实现用户角色的方式

我目前的工作在我的新的应用程序,并寻找最好的方式来实现一个功能

通过情景我需要实现

我“作为一个用户的位置有作用”已完成:

场景: 当用户将新位置添加到配置文件 其中一个需要的字段是“角色”。这可能是“客人”,“经理”或“卖家”。在模型方面完成他的最好方法是什么?

我做到了这一点与has_many_through assosiation

控制器:

def create 
    @location = Location.new(location_params) 
    @location.profiles << current_user.profile 
    #set user role 
    current_user.profile.profile_location_throughs.where(location_id: location.id).set_role(params[:location][:role]) 
    respond_to do |format| 
     if @location.save 
     .... 
     end 
    end 
end 

机型:

class Profile < ActiveRecord::Base do 
    has_many :profile_location_throughs 
    has_many :locations, through: :profile_location_throughs 
end 

class Location < ActiveRecord::Base do 
    has_many :profile_location_throughs 
    has_many :locations, through: :profile_location_throughs 
end 

class ProfileLocationThrough < ActiveRecord::Base 
    # with boolean fields: manager, seller, guest 

    belongs_to :location 
    belongs_to :profile 

    def set_role(role) 
    case role 
     when "guest" 
     self.guest = true 
     when "seller" 
     self.seller = true 
     when "manager" 
     self.manager = true 
    end 
    end 

end 

=====

问: 你可以建议更多beatiful方式实现他的功能?

+1

可以将用户在不同的地点不同的角色?如果是的话,通过关联来管理是正确的。但是,并不是只保留通过表的每个记录中的角色名称。制作一个角色表和相应的角色模型,并通过表格添加一个关联。 –

+1

我看到你有3个不同的领域,每个角色一个。看,这可能很糟糕,因为无论何时定义新角色,您都必须向模型添加新字段。相反,您应该保留单个字段“角色”并将“客人”,“经理”或“卖家”保存在其中。 –

+0

是的。在一个地点,它可能是“卖家”,在其他“客人”等等 – Art

回答

2

有几种方法可以完成基于角色的授权。

最简单的方法是通过添加enum到用户自己:

class Profile < ApplicationRecord 
    enum role: [:guest, :seller, :manager] 
end 

这是相当有限的,虽然因为它只允许“全球性”的角色。 如果你想要资源作用域角色,你需要一个连接表。

class Profile < ApplicationRecord 
    has_many :roles 
    has_many :locations, through: :roles 

    def has_role?(role, location = nil) 
    self.roles.exists?({ name: role, location: location}.compact) 
    end 

    def add_role(role, location) 
    self.roles.create!({ name: role, location: location }) 
    end 
end 

class Role < ApplicationRecord 
    belongs_to :profile 
    belongs_to :location 
end 

class Location < ApplicationRecord 
    has_many :roles 
    has_many :profiles, through: :roles 
end 

在这个例子中,我们简单地使用了roles.name列中输入字符串。如果角色的种类有限,您也可以使用枚举。如果您想使用相同的角色模型(无双关语)来限定不同类型资源上的角色,您可以使用polymorphic belongs_to relationship

class Role < ApplicationRecord 
    belongs_to :profile 
    belongs_to :resource, polymorphic: true 
end 

class Location < ApplicationRecord 
    has_many :roles, as: :resource 
    has_many :profiles, through: :roles 
end 

class OtherThing < ApplicationRecord 
    has_many :roles, as: :resource 
    has_many :profiles, through: :roles 
end 

请注意,角色只是认证解决方案的一部分。您可以将其与授权库(如PunditCanCanCan)相结合,该授权库定义了有关角色执行什么操作并强制执行这些规则的规则。

+0

非常感谢!我会以这种方式实施 – Art

相关问题