Rails 4.2:基于角色的身份验证和单独的属性
Rails 4.2: Role Based Auth and Separate Attributes
我正在创建一个包含 3 种类型用户的应用程序,最终可能会出现第 4 种类型...
- 管理员
- 提供商
- 会员(患者)
棘手的部分是每个都有一些共同的属性,例如 'first_name' 和 'last_name',但会有更多不同的属性。如果它们都共享相同的 'User' table,我的列就会太多 'nil',这感觉不是很好的做法。
解决这个问题的好方法是什么?有没有办法建立基于角色的模型关系?
我的计划是使用 Devise 和 Pundit,用于数据库的 Postgres。
您应该创建一个单独的用户模型。每个人都应该
的那三个模型(管理员、提供者、成员)
belongs_to :user
然后你可以很容易地得到 first_name 或 last_name 之类的,
member.user.first_name
或
provider.user.last_name
等等
因此,您必须在创建管理员或提供者或成员时创建用户。设计可以使用用户模型。对于角色基础的东西,你可以使用
if current_user.admin?
do something
end
希望对您有所帮助。
对所有用户类型使用单个 model/table,对 admin/provider/member 使用角色属性。然后,您可以对所有角色使用相同的登录表单,而不必在每次添加新角色时都添加更多表和模型。
我建议您查看 https://github.com/cancancommunity/cancancan 上的 CanCanCan gem。您可以根据角色授权用户操作。
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role == "admin"
can :manage, :all
elsif user.role == "provider"
can :manage, SomeModel, user_id: user.id
elsif user.role == "member"
can :read, SomeModel
can :read, SomeOtherModel
end
end
end
如果您想为每个角色使用不同的表单字段,只需为这些字段使用部分模板。
# app/views/users/_form.html.erb
<%= form_for @user do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= render "#{@user.role}_fields", f: f %>
<% end %>
# app/views/users/_admin_fields.html.erb
<%= f.text_field :some_field_for_admins_only %>
在对使用多态关联进行了大量研究之后,一位朋友提出了一个 gem,它提供了一种更简单的方法,可以通过模块模拟多Table 继承。
gem被称为Active_Record-ActsAs。
https://github.com/hzamani/active_record-acts_as
我的设置看起来与此类似:
class User < ActiveRecord::Base
actable
validates_presence_of :first_name, :last_name
def name
"#{first_name} #{last_name}"
end
end
class Member < ActiveRecord::Base
acts_as :user
end
class Provider < ActiveRecord::Base
# In case you don't wish to validate
# this model against User
acts_as :user, validates_actable: false
end
class Hospital < ActiveRecord::Base
has_many :users
end
那我需要迁移一个外键..
change_table :products do |t|
t.integer :actable_id
t.string :actable_type
end
创建用户变得容易..
Member.create(first_name: "Bob", last_name: "Miller")
我将基于“:actable_type”进行身份验证。
我正在创建一个包含 3 种类型用户的应用程序,最终可能会出现第 4 种类型...
- 管理员
- 提供商
- 会员(患者)
棘手的部分是每个都有一些共同的属性,例如 'first_name' 和 'last_name',但会有更多不同的属性。如果它们都共享相同的 'User' table,我的列就会太多 'nil',这感觉不是很好的做法。
解决这个问题的好方法是什么?有没有办法建立基于角色的模型关系?
我的计划是使用 Devise 和 Pundit,用于数据库的 Postgres。
您应该创建一个单独的用户模型。每个人都应该
的那三个模型(管理员、提供者、成员)belongs_to :user
然后你可以很容易地得到 first_name 或 last_name 之类的,
member.user.first_name
或
provider.user.last_name
等等
因此,您必须在创建管理员或提供者或成员时创建用户。设计可以使用用户模型。对于角色基础的东西,你可以使用
if current_user.admin?
do something
end
希望对您有所帮助。
对所有用户类型使用单个 model/table,对 admin/provider/member 使用角色属性。然后,您可以对所有角色使用相同的登录表单,而不必在每次添加新角色时都添加更多表和模型。
我建议您查看 https://github.com/cancancommunity/cancancan 上的 CanCanCan gem。您可以根据角色授权用户操作。
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new
if user.role == "admin"
can :manage, :all
elsif user.role == "provider"
can :manage, SomeModel, user_id: user.id
elsif user.role == "member"
can :read, SomeModel
can :read, SomeOtherModel
end
end
end
如果您想为每个角色使用不同的表单字段,只需为这些字段使用部分模板。
# app/views/users/_form.html.erb
<%= form_for @user do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= render "#{@user.role}_fields", f: f %>
<% end %>
# app/views/users/_admin_fields.html.erb
<%= f.text_field :some_field_for_admins_only %>
在对使用多态关联进行了大量研究之后,一位朋友提出了一个 gem,它提供了一种更简单的方法,可以通过模块模拟多Table 继承。
gem被称为Active_Record-ActsAs。
https://github.com/hzamani/active_record-acts_as
我的设置看起来与此类似:
class User < ActiveRecord::Base
actable
validates_presence_of :first_name, :last_name
def name
"#{first_name} #{last_name}"
end
end
class Member < ActiveRecord::Base
acts_as :user
end
class Provider < ActiveRecord::Base
# In case you don't wish to validate
# this model against User
acts_as :user, validates_actable: false
end
class Hospital < ActiveRecord::Base
has_many :users
end
那我需要迁移一个外键..
change_table :products do |t|
t.integer :actable_id
t.string :actable_type
end
创建用户变得容易..
Member.create(first_name: "Bob", last_name: "Miller")
我将基于“:actable_type”进行身份验证。