如果我执行以下操作:
@user.name = "John"
@user.url = "www.john.com"
@user.save
如果我使用after_save
@user.url = "www.johnseena.com"
@user.save
当我这样做时会发生什么?
我相信它应该因为“after_save”回调而保存该值。
如果我执行以下操作:
@user.name = "John"
@user.url = "www.john.com"
@user.save
如果我使用after_save
@user.url = "www.johnseena.com"
@user.save
当我这样做时会发生什么?
我相信它应该因为“after_save”回调而保存该值。
在我看来,如果你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
。因此,如果您对该回调有任何更新操作,那么您将再次递归:)
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
如果您修改任何 int ,after_save
它将不会被保存,因为save
它已经发生了。干预的唯一机会是回滚整个事务。如果在 中添加另一个save
,after_save
那么它将是一个无限循环。
无需对数据库执行两次查询并担心递归,您可能需要考虑在数据有效负载进入服务器之前对其进行修改。
class User < AR::Base
before_save :change_url
def change_url
url = "www.johnseena.com"
end
end
非常感谢所有在这里帮助我的人。这是解决我的问题的解决方案。我按订单模型修改如下:
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