具有独特属性的多个 Devise 模型
Multiple Devise models with unique attributes
简短说明:
我寻求架构建议并帮助在单个应用程序中实现多个 Devise 模型。
更详细的解释:
我的应用程序需要执行以下行为:
有 3 种类型的用户 (Partner
、Attendee
、Speaker
),它们有一些共同的字段和一些独特的字段(此外,这些字段可能有不同的权限,即Attendee
必须有用户名,而 Speaker
可能有,但不一定要填写此字段)。此外,不同的用户模型必须与数据库中的其他 table 有不同的关联。
用户需要能够通过单一登录表单登录,但注册表应该不同。
所以,我的第一个想法是我应该使用 Pundit
或 declarative_authorization
或其他方式按角色划分用户,但用户实际上并没有不同的角色(即权限)应用程序,他们宁愿有不同的行为,他们可能会看到不同的内容和东西,所以我继续思考。
我的第二个想法是实现 STI,在阅读了几篇关于它的文章后,我尝试用代码实现它。
我通过 rails g devise User
生成了一个 Devise User
模型,然后 运行 rails g model Attendee
对其他两个用户也是如此。
然后,我继承了我的模型 User
:
class Attendee < User
end
我的 User
迁移如下所示:
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :type
# Devise stuff ...
..................
t.timestamps null: false
end
其他的迁移是这样的:
create_table :attendees do |t|
t.string :username
t.string :company_name
t.boolean :subscription
t.timestamps null: false
end
现在我意识到创建单独的 table 是错误的。
我不得不将所有可能的字段放入 User
table,对吗?
因为现在当我尝试在 rails console
中创建任何新的 Attendee
或 Speaker
或 Partner
时,所有这三个模型都具有完全相同的字段,那些 User
模型有。
但是如果我在 User
模型中添加所有可能的字段,我将如何对字段存在进行验证?
我在这里阅读了很多关于 SO 的文章和问题,但仍然无法真正理解如何实现所有这些。
无论如何,这是满足我需要的正确方法吗?
谁能详细解释一下我应该如何从头到尾实现这种行为和功能,以及在实现模型后我应该如何使用它们?
PS:这里是 history of my migrations and the whole github repo
更新
记得另一个阻止我进行角色分离的问题:
我应该如何为不同的用户注册不同的注册表单?不同路线?我无法让用户从组合框中选择他们的角色。
您可以根据角色创建条件验证规则,但首先需要解决的是 new/edit 用户表单,仅根据角色动态显示允许的字段:
class User < ActiveRecord::Base
validates :company, presence: true, if: :is_company?
def is_company
# check for the role
self.role == 'company'
end
end
更新:您可以将一个额外的参数传递给同一个注册表单,并使用它来区分您显示的表单类型。这是最好的方式。您还可以在 UserController -> def register_user、def register_company、def register_xxxx
中创建单独的方法
简短说明:
我寻求架构建议并帮助在单个应用程序中实现多个 Devise 模型。
更详细的解释:
我的应用程序需要执行以下行为:
有 3 种类型的用户 (Partner
、Attendee
、Speaker
),它们有一些共同的字段和一些独特的字段(此外,这些字段可能有不同的权限,即Attendee
必须有用户名,而 Speaker
可能有,但不一定要填写此字段)。此外,不同的用户模型必须与数据库中的其他 table 有不同的关联。
用户需要能够通过单一登录表单登录,但注册表应该不同。
所以,我的第一个想法是我应该使用 Pundit
或 declarative_authorization
或其他方式按角色划分用户,但用户实际上并没有不同的角色(即权限)应用程序,他们宁愿有不同的行为,他们可能会看到不同的内容和东西,所以我继续思考。
我的第二个想法是实现 STI,在阅读了几篇关于它的文章后,我尝试用代码实现它。
我通过 rails g devise User
生成了一个 Devise User
模型,然后 运行 rails g model Attendee
对其他两个用户也是如此。
然后,我继承了我的模型 User
:
class Attendee < User
end
我的 User
迁移如下所示:
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :type
# Devise stuff ...
..................
t.timestamps null: false
end
其他的迁移是这样的:
create_table :attendees do |t|
t.string :username
t.string :company_name
t.boolean :subscription
t.timestamps null: false
end
现在我意识到创建单独的 table 是错误的。
我不得不将所有可能的字段放入 User
table,对吗?
因为现在当我尝试在 rails console
中创建任何新的 Attendee
或 Speaker
或 Partner
时,所有这三个模型都具有完全相同的字段,那些 User
模型有。
但是如果我在 User
模型中添加所有可能的字段,我将如何对字段存在进行验证?
我在这里阅读了很多关于 SO 的文章和问题,但仍然无法真正理解如何实现所有这些。
无论如何,这是满足我需要的正确方法吗?
谁能详细解释一下我应该如何从头到尾实现这种行为和功能,以及在实现模型后我应该如何使用它们?
PS:这里是 history of my migrations and the whole github repo
更新
记得另一个阻止我进行角色分离的问题:
我应该如何为不同的用户注册不同的注册表单?不同路线?我无法让用户从组合框中选择他们的角色。
您可以根据角色创建条件验证规则,但首先需要解决的是 new/edit 用户表单,仅根据角色动态显示允许的字段:
class User < ActiveRecord::Base
validates :company, presence: true, if: :is_company?
def is_company
# check for the role
self.role == 'company'
end
end
更新:您可以将一个额外的参数传递给同一个注册表单,并使用它来区分您显示的表单类型。这是最好的方式。您还可以在 UserController -> def register_user、def register_company、def register_xxxx
中创建单独的方法