0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

学習を進めていく中、頻繁に登場するようになってきたsavesave!。この!の有り無しだけで意味がだいぶ変わってくるなんて…。
アウトプットとしてそれぞれの違いと、簡単な例を挙げてみます。

saveメソッド

  • Active Record モデルのインスタンスをデータベースに保存します
  • 保存が成功した場合、true を返しますが、保存に失敗した場合は false を返します
  • 保存に失敗した場合、エラーが発生することなく単に false を返すだけです
# Example with save
user = User.new(name: "John")
if user.save
  puts "User saved successfully!"
else
  puts "Failed to save user."
end

save!メソッド

  • save メソッドと同様にインスタンスをデータベースに保存しますが、保存に失敗した場合には例外 ActiveRecord::RecordInvalid を発生させます
  • つまり、save! メソッドは保存が成功するか、もしくは例外が発生するまで実行がブロックされます
  • バリデーションに失敗する可能性がある場合や、データベース障害などの非常に稀なケースに対して、save!を使用することが推奨されます
# Example with save! and exception handling
# 通常の条件分岐でsave!を使用する場合例外処理を行う begin...rescue ブロックで囲む必要がある
begin
  if user.save!
    puts "User saved successfully!"
  else
    puts "Failed to save user."
  end
rescue ActiveRecord::RecordInvalid => e
  puts "Failed to save user: #{e.message}"
end
# Example with save!
begin
  user.save!
  puts "User saved successfully!"
rescue ActiveRecord::RecordInvalid => e
  puts "Failed to save user: #{e.message}"
end

似たような仕組み:create メソッド

  • save メソッドと同様にインスタンスを保存しますが、新しいレコードを作成し保存します
  • 保存に失敗した場合は、false を返します
# Example with create
user = User.create(name: "Alice")
if user.persisted?
  puts "User created successfully!"
else
  puts "Failed to create user."
end

トランザクションとの組み合わせ技

※トランザクション内で複数の save や save! を行い、それらが全て成功した場合にのみコミット(確定)、途中でどれか一つでも失敗した場合には全てをロールバック(取り消し)する、という使い方

save メソッドとトランザクションの例

ActiveRecord::Base.transaction do
  user = User.new(name: "Alice")
  if user.save
    address = Address.new(street: "123 Main St", city: "Anytown")
    if address.save
      puts "User and address saved successfully!"
    else
      raise ActiveRecord::Rollback, "Failed to save address."
    end
  else
    raise ActiveRecord::Rollback, "Failed to save user."
  end
end
  • ユーザーが保存されなかった場合には、そのユーザーに関連付けられた他のデータも同時にロールバックされるため、データベース内で不整合が生じることを防ぐことができる
  • このコードはアリスという名前で新たなユーザーを作っている。もしアリスがsaveされたら新しいアドレスを登録できる。そして新しいアドレスも無事登録出来たら成功。そうでなかったらアドレス失敗。前段階のユーザーの登録がちゃんと登録できなかったらユーザー登録失敗
  • まとめると、トランザクション開始>ユーザー保存>アドレス保存>アドレス保存失敗>ユーザー保存失敗

save! メソッドとトランザクションの例

begin
  ActiveRecord::Base.transaction do
    user = User.new(name: "Bob")
    user.save!

    address = Address.new(street: "456 Elm St", city: "Othertown")
    address.save!

    puts "User and address saved successfully!"
  end
rescue ActiveRecord::RecordInvalid => e
  puts "Failed to save user or address: #{e.message}"
end
  • ボブで登録してsaveする。アドレスを登録してsaveする。そしてユーザーとアドレス登録成功の文字。どちらかの登録でエラーが起きたらユーザーまたはアドレスの登録失敗という文字が発生
  • つまり、ユーザー保存>アドレス保存>成功時メッセージ>保存失敗時の処理

さいごに

savesave!のちがいを紹介しました。銀行なんかの引き落とし処理や重要なパスワードの処理など、厳しい基準を設けたいならトランザクションやsave!を使用したほうが安全なのかなと感じました。
少しでも参考になれば幸いです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?