Как работает after_save при сохранении объекта
Если я делаю следующее:
@user.name = "John"
@user.url = "www.john.com"
@user.save
Если я использую after_save
@user.url = "www.johnseena.com"
@user.save
Что произойдет, когда я это сделаю?
Я считаю, что он должен сохранить значение из-за обратного вызова 'after_save'.
Ответы
Ответ 1
На мой взгляд, если вы вызываете функцию save
в обратном вызове after_save
, тогда она будет ловушка в рекурсию, если вы не установите охрану в начале. как это
class User < AR::Base
after_save :change_url
def change_url
#Check some condition to skip saving
url = "www.johnseena.com"
save #<======= this save will fire the after_save again
end
end
Однако, помимо установки охраны, вы можете использовать update_column
также
def change_url
update_column(:url, "www.johnseena.com")
end
В этом случае он не срабатывает after_save
. Однако он срабатывает after_update
. Поэтому, если у вас есть операция обновления для этого вызова, вы снова находитесь в рекурсии:)
Ответ 2
Обратный вызов after_save будет запускаться независимо от сохранения или обновления на этом объекте.
Кроме того,
update_column не вызывает никаких обратных вызовов (т.е. after_update) и также пропускает проверки. см. http://apidock.com/rails/ActiveRecord/Persistence/update_column
U должен использовать after_create или after_update, в зависимости от операции и времени.
after_create :send_mail
def send_x_mail
#some mail that user has been created
end
after_update :send_y_mail
def send_y_mail
#some data has been updated
end
after_save :update_some_date
def update_some_data
...
action which doesnt update the current object else will trigger the call_back
end
Также см. В чем разница между` after_create` и `after_save` и когда использовать, что? и для обратных вызовов см. http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M000059
Ответ 3
Если вы измените что-либо int after_save
, оно не будет сохранено, так как save
уже выполнено. Единственный шанс вмешаться - это откат всей транзакции. Если вы добавите еще save
в after_save
, то это будет бесконечный цикл.
Ответ 4
Вместо того, чтобы выполнять две запросы к базе данных и беспокоиться о рекурсии, вы можете захотеть просто модифицировать полезную нагрузку данных до ее выхода на сервер.
class User < AR::Base
before_save :change_url
def change_url
url = "www.johnseena.com"
end
end
Ответ 5
Большое спасибо всем, кто помог мне здесь. Вот решение, которое решило мою проблему. Я изменил модель заказа на следующее:
class Order < ActiveRecord::Base
has_and_belongs_to_many :users
validates :item, presence: true
def add_order(username, order)
user = User.where(username: username).first
if !user.nil?
user.orders.create(item: order.item)
end
end
def remove_order(order)
end
end