読者です 読者をやめる 読者になる 読者になる

元フリーエンジニアライフ

Ruby on Rails とか MovableType とかAWSやってるフリーランスウェブエンジニアの記録でした。現在は法人成りしてIT社長。

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

Rails
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)"

こうなる。

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