#ruby-on-rails #activerecord #orm
Вопрос:
У меня есть модель пользователя с полями электронной почты, имени и кода. Электронное письмо должно быть уникальным. Есть ли в rails метод, с помощью которого я могу сделать это одним выстрелом:
создайте пользователя с определенным адресом электронной почты и кодом, если электронное письмо еще не принято, или обновите код пользователя с помощью этого электронного письма, но имя должно быть равно «abc».
или это единственный выход?
begin
user.create!(code: ..., email:...)
rescue ActiveRecord::RecordInvalid => e
if it is email taken error
User.where(name: 'abc').update(code:...)
end
end
Спасибо
Комментарии:
1. вы, вероятно, ищете User.find_or_initialize_by(электронная почта: «электронная почта»). Я не совсем понимаю, чего вы добиваетесь … если электронная почта должна быть уникальной…, почему их вторичное ограничение заключается в том, что имя должно быть равно «abc»… что вы собираетесь делать в сценарии, когда электронное письмо было принято, но присвоено какому-либо другому имени?
2. @David в сценарии, где электронная почта была взята, но присвоена какому-то другому имени, я не должен обновлять код, потому что по праву они не должны запрашивать его
3. а, понятно … тогда, вероятно, лучше всего использовать, как я предлагаю, а затем проверить имя для полученной записи.
Ответ №1:
Думаю, это то, что вы могли бы искать
user = User.find_by(email: ...) || User.new(email: ...)
user.assign_attributes(code: ...) if user.name == 'abc' || user.new_record?
user.save if user.changed?
Комментарии:
1.
user.changed?
может работать не так, как предполагалось, если в вашей модели есть столбцы Json
Ответ №2:
Что вам нужно, так это #find_or_create_by
блок:
User.find_or_create_by(email: ....) do |user|
user.code = ... if user.name == 'abc'
end
Если он найдет пользователя с указанным адресом электронной почты, блок не будет вызван.
Если он не найдет пользователя с указанным электронным письмом, он вызовет блок, который обновит код только при условии, что имя «abc»