Ruby-on-rails 保存对象时 after_save 如何工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12835029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does after_save work when saving an object
提问by SSP
If I do the following:
如果我执行以下操作:
@user.name = "John"
@user.url = "www.john.com"
@user.save
If I use after_save
如果我使用 after_save
@user.url = "www.johnseena.com"
@user.save
What will happen when I do this?
当我这样做时会发生什么?
I believe it should save the value because of the 'after_save' callback.
我相信它应该保存值,因为 'after_save' 回调。
回答by Samiron
In my opinion, if you call savefunction in a after_savecallback, then it will trap into a recursion unless you put a guard at the beginning. like this
在我看来,如果您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
However, apart from putting a guard, you can use update_columnalso
然而,除了把一个后卫,你可以使用update_column还
def change_url
update_column(:url, "www.johnseena.com")
end
In this case it will not fire after_save. However, it will fire after_update. So if you have any update operation on that call back then you are in recursion again :)
在这种情况下它不会触发after_save。但是,它会触发after_update。因此,如果您对该回调有任何更新操作,那么您将再次递归:)
回答by prasad.surase
The after_savecallback will be triggered irrespective its a saveor an updateon that object.
该after_save的回调函数会被触发,不论它是一个保存或更新该对象上。
Also,
还,
update_columndoesn't trigger any callbacks(ie after_update) and skips validations too. see http://apidock.com/rails/ActiveRecord/Persistence/update_column
update_column不会触发任何回调(即 after_update)并跳过验证。见http://apidock.com/rails/ActiveRecord/Persistence/update_column
U should specifically use after_createor after_updatedepending upon the operation and its timing.
你应该根据操作及其时间专门使用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
Also see What is the difference between `after_create` and `after_save` and when to use which?and for callbacks see http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M000059
另请参阅“after_create”和“after_save”之间有什么区别以及何时使用哪个?和回调见http://ar.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M000059
回答by Matzi
If you modify anything int the after_saveit won't be saved, as the saveis already taken place. The only chance to intervene is to rollback the whole transaction. If you add another savein the after_save, then it will be an infinite loop.
如果您修改任何 int 内容,after_save它将不会被保存,因为save已经发生了。唯一的干预机会是回滚整个事务。如果添加另一个save的after_save,那么这将是一个无限循环。
回答by ProLoser
Instead of performing two queries to the database and worrying about recursion, you may want to consider just modifying the data payload before it goes to the server.
与其对数据库执行两次查询并担心递归,您可能只想考虑在数据到达服务器之前修改数据负载。
class User < AR::Base
before_save :change_url
def change_url
url = "www.johnseena.com"
end
end
回答by CodeYogi
Many thanks to everyone who helped me out here. Here is the solution which solved my problem. I modified by order model to the following:
非常感谢在这里帮助我的所有人。这是解决我的问题的解决方案。我按订单模型修改为以下内容:
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

