Rails 4.2:基于角色的身份验证和单独的属性

时间:2015-05-19 00:36:41

标签: ruby-on-rails authentication devise authorization table-relationships

我正在使用3种类型的用户创建一个应用程序,最终可以获得第4个...

  • 管理员
  • 提供商
  • 会员(病人)

棘手的部分是每个共享一些共同属性,例如' first_name'和' last_name',但会有更多不同的属性。如果他们都共享相同的用户'表,我会有太多的专栏 ' nil'这并不是一种良好的做法。

这会是一个好方法吗?有没有办法建立基于角色的模型关系?

我的计划是使用Devise和Pundit,Postgres for DB。

3 个答案:

答案 0 :(得分:1)

您应该创建一个单独的用户模型。那三个模型(管理员,提供者,成员)每个人都应该

belongs_to :user

然后您可以轻松地使用first_name或last_name,

member.user.first_name

provider.user.last_name

因此,您必须在创建管理员或提供者或成员时创建用户。设计可以使用用户模型。对于角色基础事物,您可以使用

if current_user.admin?
  do something
end

我希望有所帮助。

答案 1 :(得分:1)

对所有用户类型使用单个模型/表,为admin / provider / member使用role属性。然后,您可以为所有这些使用相同的登录表单,并且每次添加新角色时都不必添加更多表格和模型。

我建议您在https://github.com/cancancommunity/cancancan查看CanCanCan宝石。您可以根据角色授权用户操作。

# 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 %>

答案 2 :(得分:1)

经过大量关于使用多态关联的研究后,一位朋友提出了一个gem,它提供了一种更简单的方法,可以通过模块模拟多表继承。

gem名为 Active_Record-Acts As
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”。