タケユー・ウェブ日報

Ruby on Rails や Flutter といったWeb・モバイルアプリ技術を武器にお客様のビジネス立ち上げを支援する、タケユー・ウェブ株式会社の技術ブログです。

Active::Recordのトランザクション復習

user = User.find(2)
user.name = 'takeyuweb'
user.save!

User.transaction do         # A
  user.name = 'takeyuweb(trA)'
  user.save!
  
  User.transaction do       # B
    user.name = 'takeyuweb(trB)'
    user.save!
  end
  User.transaction do   # C
    user.name = 'takeyuweb(trC)'
    user.save!
    raise
  end
end

pp user.reload.name # => "takeyuweb"

user = User.find(2)
user.name = 'takeyuweb'
user.save!

User.transaction do         # A
  user.name = 'takeyuweb(trA)'
  user.save!
  
  User.transaction do       # B
    user.name = 'takeyuweb(trB)'
    user.save!
  end
  
  User.transaction(requires_new: true) do   # C
    user.name = 'takeyuweb(trC)'
    user.save!
    raise("突き抜けろ!")
  end
end
# RuntimeError: 突き抜けろ!

pp user.reload.name # => "takeyuweb"

--

user = User.find(2)
user.name = 'takeyuweb'
user.save!

User.transaction do         # A
  user.name = 'takeyuweb(trA)'
  user.save!
  
  User.transaction do       # B
    user.name = 'takeyuweb(trB)'
    user.save!
  end
  
  User.transaction(requires_new: true) do   # C
    user.name = 'takeyuweb(trC)'
    user.save!
    raise(ActiveRecord::Rollback)
  end
end
# CのActiveRecord::Rollbackは握りつぶされてそのまま処理を継続するので

pp user.reload.name # => "takeyuweb(trB)"

user = User.find(2)
user.name = 'takeyuweb'
user.save!

User.transaction do         # A
  User.transaction do       # B
    user.name = 'takeyuweb(trB)'
    user.save!
  end
  
  User.transaction(requires_new: true) do   # C
    user.name = 'takeyuweb(trC)'
    user.save!
    raise(ActiveRecord::Rollback)
  end
  
  user.name = 'takeyuweb(trA)'
  user.save!
end

pp user.reload.name # => "takeyuweb(trA)"

こうなる。

そのまま処理を継続してしまうとよくわかって使うこと