after_commit回调被多次调用 [英] after_commit callback is being called several times
问题描述
update:
是否是对update_attributes的调用获取它自己的事务的情况?
update: Is it the case that a call to update_attributes gets it's own transaction?
I've looked at this question and for reasons in addition to that question, i've decided to go with after_commit as the proper hook. The problem is it's being called multiple (exactly three) times. The code is a little complex to explain, but basically there is a profile model that has
include Traits::Blobs::Holder
in holder.rb我有:
in holder.rb I have:
module ClassMethods
def belongs_to_blob(name, options = {})
clazz = options[:class_name] ? options[:class_name].constantize : Blob
foreign_key = options[:foreign_key] || :"#{name}_id"
define_method "save_#{name}" do
blob = self.send(name)
if self.errors.any? && blob && blob.valid?
after_transaction do
blob.save!
#self[foreign_key] = blob.id
#save resume anyway
self.update_attribute(foreign_key, blob.id)
end
end
end
after_validation "save_#{name}"
belongs_to name, options
accepts_nested_attributes_for name
end
end
终于在profile.rb本身我有:
finally in profile.rb itself I have:
after_commit :send_messages_after_registration!
protected
def send_messages_after_registration!
Rails.logger.debug("ENTERED : send_messages_after_registration " + self.owner.email.to_s)
if self.completed?
Rails.logger.debug("completed? is true " + self.owner.email.to_s)
JobSeekerNotifier.webinar_notification(self.owner.id).deliver
Resque.enqueue_in(48.hours, TrackReminderWorker, self.owner.id)
end
end
看来方法是输入3次。
it appears that the method is entered 3 times. I've been trying to figure this out for a few days so any guidance you can provide will be appreciated.
控制器代码:
def create
@user = Customer.new(params[:customer].merge(
:source => cookies[:source]
))
@user.require_password = true
respond_to do |f|
if @user.save
promote_provisional_user(@user) if cookies[:provisional_user_id]
@user.profile.update_attributes(:firsttime => true, :last_job_title => params[:job_title]) unless params[:job_title].blank?
if params[:resume]
@user.profile.firsttime = true
@user.profile.build_resume(:file => params[:resume])
@user.profile.resume.save
@user.profile.save
end
...
end
推荐答案
因此,它发生了3次,因为配置文件被保存3次:一次当用户被保存用户accept_nested_attributes_for:profile
,一次当您调用 update_attributes(:first_time => true,...)
当你调用保存在如果params [:resume]
块。每个保存创建一个新的事务(除非一个已经在进行中),你结束多个调用 after_commit
So it's happening 3 times because the profile is being saved 3 times: once when the user is saved (I assume that User accepts_nested_attributes_for :profile
, once when you call update_attributes(:first_time => true,...)
and once when you call save in the if params[:resume]
block. Every save creates a new transaction (unless one is already in progress) you end up with multiple calls to after_commit
after_commit
:on 选项(其可以取值:create
,:update
,:destroy
),以便你可以限制它到新的记录。这将明显地激活第一次保存,所以你不能看到配置文件的resumé等等。
after_commit
does take an :on
option (which can take the values :create
, :update
, :destroy
) so that you can limit it to new records. This would obviously fire on the first save so you wouldn't be able to see the profile's resumé and so on.
您可以在单个事务中包含这些更新的全部内容,在这种情况下, after_commit
一次,无论在事务中发生多少保存,通过执行像
You could in addition wrap the entirety of those updates in a single transaction, in that case after_commit
only gets called once, no matter how many saves take place inside the transaction by doing something like
User.transaction do
if @user.save
...
end
end
如果发生异常,事务将被回滚(如果你想要救助,你可以 ActiveRecord :: Rollback
)
The transaction will get rolled back if an exception is raised (you can raise ActiveRecord::Rollback
if you want to bail out)
这篇关于after_commit回调被多次调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!