У меня есть приложение rails, в котором есть три разных типа пользователей, и мне нужно, чтобы все они делились одной и той же общей информацией профиля. Однако каждый отдельный пользователь также имеет уникальные атрибуты. Я не уверен, как разделить разные поля.
Я использую devise для аутентификации и cancan для авторизации. Поэтому у меня есть модель пользователя с набором ролей, которые можно применить к пользователю. Этот класс выглядит так:
class User < ActiveRecord::Base
#... devise stuff omitted for brevity...
# Roles association
has_many :assignments
has_many :roles, :through => :assignments
# For cancan: https://github.com/ryanb/cancan/wiki/Separate-Role-Model
def has_role?(role_sym)
roles.any? { |r| r.name.underscore.to_sym == role_sym }
end
end
У каждого пользователя есть профиль, который включает:
Я не хочу загрязнять Модель пользователя с этой информацией, поэтому я добавляю ее в модель профиля. Эта часть довольно проста. Это превращает модель пользователя во что-то вроде этого:
class User < ActiveRecord::Base
#... devise stuff omitted for brevity...
#... cancan stuff omitted for brevity...
has_one :profile
end
Дополнительные поля — это то место, где у меня есть некоторые непростые чувства по поводу того, как моделировать...
Если пользователь является администратором, у него будут уникальные поля, такие как:
Если пользователь является владельцем, у него будут уникальные поля...
Если пользователь является участником, у него будет несколько дополнительных полей, таких как:
...
, а модель магазина будет содержать _много членов, поэтому мы работаем с членами магазина.
Проблема связана с дополнительными полями. Я устанавливаю их как разные классы? Поместите их в другой В настоящее время я пробовал несколько разных способов настроить это.:
Один из способов — настроить модель пользователя как совокупный корень.
class User < ActiveRecord::Base
#...
# Roles association
has_many :assignments
has_many :roles, :through => :assignments
# Profile and other object types
has_one :profile
has_one :admin
has_one :owner
has_one :member
#...
end
Преимущество этого подхода в том, что модель пользователя является корнем и может получить доступ ко всему. Ошибка заключается в том, что если пользователь является «владельцем», то ссылки «admin» и «member» будут нулевыми (, а декартово значение других возможностей -admin, но не владелец или член и т. д. ).
Другой вариант, о котором я думал, заключался в том, чтобы каждый тип пользователя наследовался от модели User как таковой:
class User < ActiveRecord::Base
#... other code removed for brevity
has_one :profile
end
class Admin < User
# admin fields
end
class Owner < User
# owner fields
end
class Member < User
# member fields
end
Проблема в том, что я загрязняю объект User всеми видами nil в таблице, где один тип не нужны значения из другого типа/и т.д. Просто кажется немного грязным, но я не уверен.
Другой вариант состоял в том, чтобы создать каждый тип учетной записи как корневой, но сделать пользователя дочерним объектом, как показано ниже.
class Admin
has_one :user
# admin fields go here.
end
class Owner
has_one :user
# owner fields go here.
end
class Member
has_one :user
# member fields go here.
end
Проблема с вышеизложенным заключается в том, что я не уверен, как загрузить правильный класс после того, как пользователь войдет в систему. У меня будет его идентификатор пользователя _, и я смогу определить, какую роль он выполняет (из-за ассоциации ролей в пользовательской модели ), но я не уверен, как перейти от пользователя UP к корневому объекту. Методы? разное?
Заключение У меня есть несколько разных способов сделать это, но я не уверен, что такое правильный подход "rails". Как правильно смоделировать это в rails AR? (Серверная часть MySQL ). Если нет «правильного» подхода, что лучше из вышеперечисленного (Я также открыт для других идей ).
Спасибо!