Как использовать драгоценный камень Devise в приложении Rails, где "Пользователь" разделяется между тремя моделями
Скажем, у меня есть следующее приложение Rails 4:
class Person < ActiveRecord::Base
has_many :email_addresses, as: :emailable
has_one :user_account
end
class EmailAddress < ActiveRecord::Base
belongs_to :emailable, polymorphic: true
# There is an :address column
end
class UserAccount < ActiveRecord::Base
belongs_to :person
end
У человека может быть несколько адресов электронной почты. У человека также может быть учетная запись пользователя. (Я переместил это в свою собственную модель, потому что не все люди будут пользователями.) Любой пользовательский адрес электронной почты может использоваться как "имя пользователя" при входе в систему.
Учитывая это, я хотел бы использовать драгоценный камень Devise. Я вижу, вы можете указать модель, к которой применяется аутентификация. User
широко используется, но я бы использовал UserAccount
. Тем не менее, Devise ожидает, что поле электронной почты (имя пользователя) будет в этой модели.
Когда пользователь регистрирует учетную запись пользователя, на самом деле будет создано три связанные записи (Person, EmailAddress и UserAccount). Я не могу понять, как заставить Devise работать с этой настройкой. Есть идеи? Спасибо за любую помощь.
Ответы
Ответ 1
Одним из вариантов было бы делегирование метода электронной почты из вашего UserAccount
в вашу модель электронной почты и переопределение поисковика def self.find_first_by_auth_conditions(warden_conditions)
, используемого процедурой входа в систему. Я нашел довольно приятное сообщение в блоге, в котором подробно описывается это, и еще один fooobar.com/questions/377419/... который имеет тот же подход. Существует также раздел в документах о том, как подтвердить создание учетной записи несколькими сообщениями электронной почты.
Поскольку ваша установка немного сложнее, вы также можете использовать EmailAddress в качестве своей основной модели разработки и делегировать методы пароля для UserAccount
.
Это может быть полезно, если вам нужно подтвердить каждый адрес электронной почты с подтверждением, а не только на учетную запись пользователя. Эта настройка заставила бы вас переопределить этот поисковик, но вы можете столкнуться с другими проблемами с делегированным паролем, который никогда не использовался ранее.
Ответ 2
Если вы используете ActiveRecord,
Сначала добавьте
attr_accessor :email
to user_account
(я думаю, что это самый простой способ справиться с формой разработки)
Далее, вам нужно изменить процедуру входа в систему. Тем не менее, в вашем user_account, переопределите метод разработки, такой
def self.find_for_database_authentication(warden_conditions)
conditions = warden_conditions.dup
if email = conditions.delete(:email)
where(conditions.to_h).includes(:email_addresses).where(email_addresses: {email: email}).first
else
where(conditions.to_h).first
end
end
вам также может потребоваться определить следующее, чтобы получить работу над кодом выше
class UserAccount < ActiveRecord::Base
belongs_to :person
has_many :email_addresses, through: :person
Это должно сработать, я проверил это, используя активную запись, но если вы используете mongoid, возможно, решение будет другим.
Обратите внимание, что я изменил код из deva Как разрешить пользователям выполнять вход с использованием имени пользователя или адреса электронной почты для получения решение.