我在用户模型中使用枚举实现的用户具有角色:
enum role: [:staff, :clinician]
我有一个大学模型,用户为belongs_to:university,大学模型为has_many:users。
我的应用程序的工作方式是"员工"将属于大学,但"临床医生"是私人执业,因此不需要属于大学,也不需要在注册期间选择一个。
如果用户选择了临床医生,我的注册表单设置为隐藏大学字段,但我想确保我的验证设置为要求任何选择注册人员的用户也必须选择一所大学任何在注册时选择临床医生的用户如果选择了大学,将无法通过验证。
以下是用户注册表单的角色部分:
<%= f.label :role %>
<%= f.select(:role, User.roles.keys.map {|role| [role.titleize,role]}, :include_blank => "Please Select", id: 'user_role') %>
<%= content_tag :div, class: 'js-dependent-fields', data: { 'select-id': 'user_role', 'option-value': 'staff'} do %>
<%= f.label :university_id%>
<%= collection_select( :user, :university_id, University.all, :id, :name, prompt: true) %>
答案 0 :(得分:2)
它需要更多的额外设置,但我认为随着时间的推移,灵活性会得到回报:
尝试将单表继承与您的枚举角色结合使用。您将能够更轻松地为不同角色定义单独的回调,验证,范围和关联,同时继承您希望它们共享的共享。例如,您只能将其设为Staff belongs_to :university
,而Clinician
则不会。
# Stripped down schema
create_table "universities", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "university_id"
t.integer "role"
t.index ["university_id"], name: "index_users_on_university_id"
end
# Models
class University < ApplicationRecord
has_many :staffs
end
class User < ApplicationRecord
self.inheritance_column = :role
enum role: { Staff: 0, Clinician: 1 }
end
class Clinician < User
end
class Staff < User
belongs_to :university
end
Staff.first.university # => returns instance of University
Clinician.first.university # => raises NoMethodError
University.first.staffs # => returns collection of Staff objects
University.first.clinicians # => raises NoMethodError
请注意,没有type
列。通过设置role:integer
,它被enum
用于self.inheritance_column = :role
的列覆盖了。您可以使用字符串/符号表示与enum
角色进行互动("Staff"
,Staff.new
,User.first.Staff?
,User.first.Staff!
,User.new(role: "Staff")
和ActiveRecord小心地将该字符串转换为数据库查询的正整数。
例如,这是User.where(role: "Staff")
SELECT "users".* FROM "users" WHERE "users"."role" = 0
Staff.all
返回相同的结果,但查询的措辞略有不同
SELECT "users".* FROM "users" WHERE "users"."role" IN (0)
有关详细信息,请参阅此问题:Same Model with different columns Rails
答案 1 :(得分:1)
您可以为User.rb模型中的validates
电话提供条件:
validates :university, presence: true, if: lambda { self.role.to_s == 'staff' }
# watch out for symbol vs. string in your self.role array
我认为(从未这样做过但我想这会有用)你可以为:clinician
角色做到这一点:
validates :university, presence: false, if: lambda { self.role.to_s == 'clinician' }