如果我执行以下操作:
@user.name = "John"
@user.url = "www.john.com"
@user.save
如果我使用after_save
@user.url = "www.johnseena.com"
@user.save
当我这样做会发生什么?
我认为它应该保存值,因为'after_save'回调。
答案 0 :(得分:32)
在我看来,如果你在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
。因此,如果您对该回调有任何更新操作,那么您再次进行递归:)
答案 1 :(得分:6)
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
另见What is the difference between `after_create` and `after_save` and when to use which?,有关回调,请参阅http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M000059
答案 2 :(得分:4)
如果您修改after_save
中的任何内容,则不会保存,因为save
已经发生。干预的唯一机会是回滚整个交易。如果您在save
中添加另一个after_save
,那么它将是一个无限循环。
答案 3 :(得分:1)
您可能只想考虑在数据有效负载进入服务器之前修改数据有效负载,而不是对数据库执行两次查询并担心递归。
class User < AR::Base
before_save :change_url
def change_url
url = "www.johnseena.com"
end
end
答案 4 :(得分:0)
非常感谢帮助我的所有人。这是解决我的问题的解决方案。我按订单模型修改了以下内容:
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