#New_record? функция определяет, была ли сохранена запись. Но на after_save
крючке всегда ложно . Есть ли способ определить, является ли запись новой записью или старой после обновления?
Я надеюсь не использовать другой обратный вызов, например, before_create
чтобы установить флаг в модели или потребовать другой запрос в базу данных.
Любой совет приветствуется.
Edit: Нужно, чтобы определить его в after_save
крюке, и для моего конкретного случая использования, нет updated_at
или updated_on
метку времени
ruby-on-rails
activerecord
activemodel
Аарон Цянь
источник
источник
Ответы:
Я хотел использовать это для
after_save
обратного вызова.Более простое решение - использовать
id_changed?
(поскольку оно не изменитсяupdate
) или дажеcreated_at_changed?
при наличии столбцов с отметками времени.Обновление: как указывает @mitsy, если эта проверка необходима вне обратных вызовов, используйте
id_previously_changed?
. См. Документы .источник
after_save
.id_changed?
будет ложным после сохранения записи (по крайней мере, за пределами хуков). В таком случае можно использоватьid_previously_changed?
Насколько я знаю, здесь нет рельсовой магии, тебе придется сделать это самому. Вы можете очистить это с помощью виртуального атрибута ...
В вашем классе модели:
источник
Еще один вариант для тех, у кого есть
updated_at
временная метка:источник
created_at
лиupdated_at
в обратном вызове выполнить равенство вafter_save
любое время, кроме того, когда он был впервые создан?"created_at
иupdated_at
будет равно в обратном вызовеafter_save
. Во всех других ситуациях они не будут равны вafter_save
обратном вызове.Существует
after_create
обратный вызов, который вызывается только в том случае, если запись является новой записью, после ее сохранения . Существует такжеafter_update
обратный вызов для использования, если это была существующая запись, которая была изменена и сохранена.after_save
Обратного вызова вызывается в обоих случаях, после того какafter_create
илиafter_update
называется.Используйте,
after_create
если вам нужно, чтобы что-то произошло один раз после сохранения новой записи.Подробнее здесь: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html
источник
Поскольку объект уже был сохранен, вам нужно будет просмотреть предыдущие изменения. Идентификатор должен изменяться только после создания.
Также есть переменная экземпляра
@new_record_before_save
. Вы можете получить к нему доступ, выполнив следующие действия:Оба довольно уродливые, но они позволят вам узнать, был ли объект создан заново. Надеюсь, это поможет!
источник
after_save
обратного вызова с использованием Rails 4, и ни один из них не работает, чтобы идентифицировать эту новую запись.@object.previous_changes[:id].any?
это довольно просто и элегантно. У меня работает после обновления записи (откуда не звонюafter_save
).@object.id_previously_changed?
немного менее некрасиво.after_save
Rails 4, на который вы бы хотели посмотретьchanges[:id]
вместоprevious_changes[:id]
. Однако это изменилось в Rails5.1 (см. Обсуждение в github.com/rails/rails/pull/25337 )previous_changes.key?(:id)
для лучшего понимания.Способ Rails 5.1+:
источник
Для Rails 4 (проверено на 4.2.11.1) результаты
changes
иprevious_changes
методы - это пустые хэши{}
при создании объекта внутриafter_save
. Так чтоattribute_changed?
такие методыid_changed?
не будут работать должным образом.Но вы можете воспользоваться этим знанием и, зная, что при
changes
обновлении должен присутствовать хотя бы 1 атрибут, проверьте, неchanges
является ли он пустым. Как только вы подтвердите, что он пуст, вы должны быть во время создания объекта:источник
Мне нравится быть конкретным, даже если я знаю, что
:id
обычно это не должно измениться, ноВсегда дешевле быть конкретным, чем найти очень странную неожиданную ошибку.
Точно так же, если я ожидаю
true
флага от недостоверного аргументаЭто экономит много часов, чтобы не сидеть на странных ошибках.
источник