after_commit回调被多次调用 [英] after_commit callback is being called several times

查看:150
本文介绍了after_commit回调被多次调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆