0

これは、Railsアプリケーションのバックグラウンドアクティビティをトレースするために作成したクラスです。

私の問題は、statusフィールドが正しく更新されているのに、logsフィールドが更新されていないことです。なぜですか?

ps1:tmp_logs必要なデータ、つまりルートディレクトリから見つかったhtmlファイルのリストを含むログを確認できます)

ps2:このコードはrakedelayed_jobgemを介して実行されます。

class MaintenanceOperation < ActiveRecord::Base
  attr_accessible :logs, :status, :operation

  def track_object_elements_in_html
    status = "started"
    tmp_logs = logs
    self.save
    begin
      nb_files = 0
      html_files = File.join(my_root, "**", "*.{html,htm,HTML,HTM}")
      Dir.glob(html_files).each do |file|
        nb_files += 1
        tmp_logs << file << "\n"
        logger.debug tmp_logs
      end
      tmp_logs << "Found #{nb_files} files." << "\n"
      self.logs = tmp_logs

      self.status = "done"
    rescue Exception => e
      logger.error "Finished performing maintenance operation with error"
      logger.error e.message
      e.backtrace.each { |line| logger.error line }
      logger.error "Flagging as error"
      self.status = "error"
    end
    self.save
  end
end

編集:

を変更した後に保存すると、ログに空のトランザクションが表示されますlogs

2013-02-18 19:15:28.981 [meh]  (0.1ms)  begin transaction (pid:80725)
2013-02-18 19:15:28.982 [meh]  (0.0ms)  commit transaction (pid:80725)
4

1 に答える 1

0

ここでアクティブレコードの変更追跡に巻き込まれていると思います。一言で言えば、save Active Recordを呼び出すと、更新したと思われる列のみが更新されます。特に、その場で属性を変更した場合(たとえば、gsub!または<<を呼び出した場合)、ActiveRecordはそれを検出しません。

あなたがやっている

self.logs = tmp_logs

ただし、tmp_logs以前はに設定されていたlogsためself.logs、とtmp_logsは同じオブジェクトです。割り当てを行う時点で、Active Recordはself.logsとtmp_logsを比較し、それらが同じオブジェクトであることを確認するため、列を変更済みとしてマークしません。

Active Recordがログ列に新しい値を割り当てていると見なすようにコードを変更するか(たとえば、tmp_logsをself.logs.dupに設定)、呼び出しlogs_will_change!てActiveRecordに属性を変更したことを通知できます。次回saveが呼び出されたときに更新する必要があります。

于 2013-02-18T18:17:20.923 に答える