7
6

More than 5 years have passed since last update.

transactionを使用するときの注意点

Posted at

結構調べて対応したので、メモしておきます。

transactionとは

ソフトウェアの処理方式の一つで、互いに関連・依存する複数の処理をまとめ、ひとつの処理単位として扱うこと。つまり複数の処理をひとつの処理として考えるということで処理A、処理Bをひとつの処理Cとして扱う。処理Aが終了し処理Bを実行しているときにエラーが起こると処理Cがなかったことになる(この場合処理Aがなかったことになるということ)。

delete もしくは destroyを使用したとき

コントローラの中で要素を削除するという処理を加え、保存するときにこのtransactionを使用してみた。で例外処理としてその要素にnilを入れたかったので以下のようなコードにした。

if client_attributes[:client_hoge_attributes]
  @client_temp.client_hoge.each { |obj| obj.delete }
  client_attributes[:client_hoge_attributes].each do |key, val|
    if client_attributes[:client_hoge_attributes][key]
      client_attributes[:client_hoge_attributes][key].delete("id")
    end
  end
end
@client_temp.attributes = client_attributes
@client_temp.delete_blank
begin
  ClientTemp.transaction do
    @client_temp.save! validate: @client_temp.applied?
    @client_temp.client.update_photo_used
  end
  if @client_temp.temp?
    flash[:notice] = I18n.t "clients.update.temp"
  else
    flash[:notice] = I18n.t "clients.update.offer"
  end
  redirect_to client_top_path and return
rescue
  @errors = @client_temp.errors
  @client_temp.client_hoge.each{|obj| obj.client_temp_id = nil }
  @client_temp.fill_blank
  render action: :edit
end

特定の条件下でRuntimeError Can't modify frozen hashというエラー発生!
こいつがやっかいだった。

RuntimeError Can't modify frozen hash

これの意味は「オブジェクトの中身を変更できなくなっている」のに変更をしようとしているので出るエラー。
transactionのブロック内で破壊的メソッドのsave!をしている。ここで例外処理に移ったときdeleteで削除されているidも絡んで起こるエラーっぽいです。
いまいち腑に落ちていないのですがまあ対応してみた。

方法

freezeを解除する方法があれば解決するのでは?とあたりをつけて調べてみた。
dup を使えばほぼ同じ内容の凍結されていないオブジェクトを得ることはできます。とかこういうのを参考にしました。ActiveRecord オブジェクトをコピーする
ってことで

rescue
  @errors = @client_temp.errors
 @client_temp = @client_temp.dup
  @client_temp.client_hoge.each{|obj| obj.client_temp_id = nil }
  @client_temp.fill_blank
  render action: :edit
end

みたいに対応してみたら、、、成功!!

エラーの意味の詳細がわかり次第、更新します。

レファレンスtransaction

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6