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”进行身份验证。