Рейки 6
Rails 6 додав upsert
і upsert_all
методи, що забезпечують цю функціональність.
Model.upsert(column_name: value)
[upsert] Він не створює екземплярів будь-яких моделей, а також не викликає зворотних викликів або перевірок Active Record.
Рейки 5, 4 та 3
Ні, якщо ви шукаєте тип оператора "upsert" (де база даних виконує оновлення або оператор вставки в тій самій операції). Нестандартно Rails та ActiveRecord не мають такої функції. Тим не менш, ти можеш використовувати самоцвіт upsert .
В іншому випадку ви можете використовувати: find_or_initialize_by
або find_or_create_by
, які пропонують подібну функціональність, хоча і за рахунок додаткового звернення до бази даних, що, в більшості випадків, навряд чи є проблемою. Отже, якщо у вас немає серйозних проблем з продуктивністю, я б не використовував самоцвіт.
Наприклад, якщо жодного користувача не знайдено з іменем "Роджер", новий екземпляр користувача створюється із name
встановленим значенням "Роджер".
user = User.where(name: "Roger").first_or_initialize
user.email = "email@example.com"
user.save
Крім того, ви можете використовувати find_or_initialize_by
.
user = User.find_or_initialize_by(name: "Roger")
У рейках 3.
user = User.find_or_initialize_by_name("Roger")
user.email = "email@example.com"
user.save
Ви можете використовувати блок, але блок запускається, лише якщо запис новий .
User.where(name: "Roger").first_or_initialize do |user|
# this won't run if a user with name "Roger" is found
user.save
end
User.find_or_initialize_by(name: "Roger") do |user|
# this also won't run if a user with name "Roger" is found
user.save
end
Якщо ви хочете використовувати блок незалежно від збереження запису, використовуйте tap
результат:
User.where(name: "Roger").first_or_initialize.tap do |user|
user.email = "email@example.com"
user.save
end