Rails save vs save! の違い|戻り値・例外・関連メソッド・使い分けを徹底解説
Rails でレコードを保存する2大メソッド:
user = User.new(name: "Alice", email: "alice@example.com")
user.save # 通常版
user.save! # ビックリマーク版(例外発生版)
! 1つの違いですが、挙動が決定的に違う:
save: バリデーション失敗でfalseを返すsave!: バリデーション失敗でActiveRecord::RecordInvalid例外
しかし、
- どちらをいつ使うべき?
create!/update!/destroy!も同じパターン?- コントローラとモデルで使い分けはある?
- トランザクション内では?
- エラーをどう処理すべき?
など、Rails 開発で必ず出会う判断基準が多くあります。
本記事では、save / save! のすべての違いを、戻り値、発生例外、関連メソッド比較、コールバックとの関係、トランザクション内での挙動、コントローラ・モデル・ジョブごとの使い分け、エラーハンドリングパターン、ありがちな間違いまで完全網羅します。この1本で Rails の保存処理を安全かつ意図通りに書けるようになります。
- 1. 結論:違いを一発で理解
- 2. まず押さえる:save の基本
- 3. まず押さえる:save! の基本
- 4. 戻り値 vs 例外、どちらが良いか
- 5. 関連メソッドの早見表
- 6. ActiveRecord 例外の詳細
- 7. バリデーションとコールバックの挙動
- 8. トランザクション内での挙動
- 9. 使い分け指針
- 10. エラーハンドリングのベストプラクティス
- 11. ありがちな間違い
- 12. valid? / errors の活用
- 13. 関連メソッド早見表
- 14. よくある質問(FAQ)
- 14.1. Q1. save と save! どちらを使うべき?
- 14.2. Q2. RecordInvalid のメッセージカスタマイズ
- 14.3. Q3. save(validate: false) はいつ使う?
- 14.4. Q4. save! の例外を rescue すべきか
- 14.5. Q5. update_columns との違い
- 14.6. Q6. トランザクションの自動 rollback 条件
- 14.7. Q7. save! が成功するか確認したい
- 14.8. Q8. 既存レコードの save とは
- 14.9. Q9. save の前後にロジック
- 14.10. Q10. save 後のエラーチェック
- 14.11. Q11. ネストした関連保存
- 14.12. Q12. saveメソッドの内部動作
- 15. 参考リンク・関連資料
- 16. まとめ
結論:違いを一発で理解
時間がない方向けに、最重要ポイントを先に示します。
早見表
| 観点 | save | save! |
|---|---|---|
| 戻り値(成功) | true | true |
| 戻り値(バリデーション失敗) | false | – |
| 発生例外(バリデーション失敗) | なし | ActiveRecord::RecordInvalid |
| 戻り値(DB保存失敗) | false | – |
| 発生例外(DB保存失敗) | なし | ActiveRecord::RecordNotSaved |
| callback halt時 | false 返却 | ActiveRecord::RecordNotSaved |
| トランザクション内 | 成功するなら commit | 同上、失敗で自動 rollback |
| エラー情報の取得 | record.errors | 例外+ record.errors |
| 適している場面 | エラーで分岐したい | エラーは異常とみなす |
一言で言うと
save: 失敗を戻り値で判定したい時(フォーム送信等)save!: 失敗が**想定外(バグ)**である時(内部処理・トランザクション)
詳細は以下で解説します。
まず押さえる:save の基本
save の使い方
user = User.new(name: "Alice", email: "alice@example.com")
if user.save
puts "保存成功"
else
puts "保存失敗"
puts user.errors.full_messages
end
save の戻り値
| 結果 | 戻り値 |
|---|---|
| 成功 | true |
| バリデーション失敗 | false |
| DB保存失敗 | false |
| before_save コールバックで halt | false |
バリデーション失敗時
class User < ApplicationRecord
validates :email, presence: true
end
user = User.new(name: "Alice")
user.save
# => false
user.errors.full_messages
# => ["Email can't be blank"]
Controller での典型パターン
class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
redirect_to @user, notice: "登録成功"
else
render :new, status: :unprocessable_entity
end
end
end
save の戻り値で分岐し、失敗時は再表示。これは Rails 標準のパターン。
まず押さえる:save! の基本
save! の使い方
user = User.new(name: "Alice", email: "alice@example.com")
user.save! # 失敗すると例外
失敗時の例外
user = User.new(name: "Alice") # email 無し
user.save!
# => ActiveRecord::RecordInvalid: Validation failed: Email can't be blank
例外の捕捉
begin
user.save!
rescue ActiveRecord::RecordInvalid => e
puts "Validation failed: #{e.message}"
puts e.record.errors.full_messages
end
e.record で問題のレコードオブジェクトにアクセス可能。
save! が向くケース
- 失敗が想定外な場面(内部処理)
- トランザクション内(失敗で自動rollback)
- rake task / job で確実にエラーを通知したい
- テストで「絶対に成功するはず」を強制したい
戻り値 vs 例外、どちらが良いか
save(戻り値)パターン
def signup(params)
user = User.new(params)
if user.save
UserMailer.welcome(user).deliver_later
{ success: true, user: user }
else
{ success: false, errors: user.errors.full_messages }
end
end
メリット:
- エラー処理が戻り値で完結
- 通常フローと例外フローが線形
デメリット:
- 判定漏れしやすい(
saveの戻り値を見ない) - ネストが深くなる
save!(例外)パターン
def signup(params)
user = User.new(params)
user.save!
UserMailer.welcome(user).deliver_later
user
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error "Signup failed: #{e.message}"
raise
end
メリット:
- 失敗を明示的に通知(無視できない)
- トランザクション内で自動 rollback
- 通常フローがシンプル
デメリット:
- 例外捕捉漏れで500エラーに
- パフォーマンス(例外コスト)
Rails 公式の指針
The bang versions (methods that end with an exclamation mark, like save!) raise an exception if the record is invalid. The non-bang versions – save and update returns false, and create returns the object.
「フォームのバリデーションは save、内部処理は save!」が一般的なベストプラクティス。
関連メソッドの早見表
save 以外にも bang/non-bang のペアが多数存在。
create vs create!
# create: 失敗時はオブジェクト返却(new_record? == true)
user = User.create(email: "")
user.persisted?
# => false(保存されてない)
user.errors.full_messages
# => ["Email can't be blank"]
# create!: 失敗時は例外
user = User.create!(email: "")
# => ActiveRecord::RecordInvalid
update vs update!
# update: 失敗時に false
result = user.update(email: "")
# => false
# update!: 失敗時に例外
user.update!(email: "")
# => ActiveRecord::RecordInvalid
update_attribute(要注意)
# update_attribute: バリデーションスキップで保存(危険)
user.update_attribute(:email, "")
# 検証なしで保存される!
⚠️ update_attribute はバリデーションを無視するため、業務コードでは基本使わない。
destroy vs destroy!
# destroy: 失敗時に false(before_destroy コールバックで halt等)
result = user.destroy
# => false(halt時)
# destroy!: 失敗時に例外
user.destroy!
# => ActiveRecord::RecordNotDestroyed
完全比較表
| 通常版 | bang版 | 失敗時挙動 |
|---|---|---|
save | save! | false / RecordInvalid |
create | create! | オブジェクト / RecordInvalid |
update | update! | false / RecordInvalid |
destroy | destroy! | false / RecordNotDestroyed |
find_by | find_by! | nil / RecordNotFound |
first | first! | nil / RecordNotFound |
last | last! | nil / RecordNotFound |
take | take! | nil / RecordNotFound |
toggle | toggle! | 保存しない / 保存(save!) |
Rubyの慣習
! 付きメソッドは Ruby全般で「より破壊的または例外発生」を意味する慣習:
# String
"abc".upcase # => "ABC"(新オブジェクト)
"abc".upcase! # 自身を変更(または変化なしで nil)
# Array
arr.compact # 新配列
arr.compact! # 自身から nil 除去
# ActiveRecord
user.save # 戻り値で結果通知
user.save! # 失敗で例外
ActiveRecord 例外の詳細
ActiveRecord::RecordInvalid
begin
user.save!
rescue ActiveRecord::RecordInvalid => e
e.message # => "Validation failed: Email can't be blank"
e.record # => 該当のモデルインスタンス
e.record.errors # => ActiveModel::Errors
end
ActiveRecord::RecordNotSaved
class User < ApplicationRecord
before_save :prevent_save
def prevent_save
throw(:abort) # コールバックで halt
end
end
User.new(email: "...").save
# => false(バリデーションはOKだがコールバックでhalt)
User.new(email: "...").save!
# => ActiveRecord::RecordNotSaved
ActiveRecord::RecordNotDestroyed
class User < ApplicationRecord
before_destroy :prevent_destroy
def prevent_destroy
throw(:abort) if admin?
end
end
User.find(1).destroy
# => false(halt)
User.find(1).destroy!
# => ActiveRecord::RecordNotDestroyed
例外の継承関係
ActiveRecord::ActiveRecordError
├── ActiveRecord::RecordNotFound
├── ActiveRecord::RecordInvalid
├── ActiveRecord::RecordNotSaved
├── ActiveRecord::RecordNotDestroyed
└── ActiveRecord::StatementInvalid
詳細はActiveRecord::RecordNotFound の記事も参照。
バリデーションとコールバックの挙動
バリデーション失敗の流れ
user = User.new(email: "")
# 1. user.save 呼び出し
# 2. before_validation コールバック実行
# 3. validations 実行 → 失敗
# 4. after_validation コールバック実行(失敗時も呼ばれる)
# 5. save: false 返却 / save!: RecordInvalid
class User < ApplicationRecord
before_validation :normalize_email
after_validation :log_validation_result
validates :email, presence: true
private
def normalize_email
self.email = email.downcase.strip if email.present?
end
def log_validation_result
Rails.logger.info "Validation result: #{valid?}"
end
end
before_save での halt
class User < ApplicationRecord
before_save :check_quota
private
def check_quota
if User.count >= 1000
errors.add(:base, "ユーザー上限に達しました")
throw(:abort) # ← 保存中止
end
end
end
user.save
# => false
user.save!
# => ActiveRecord::RecordNotSaved
⚠️ Rails 5+ では return false ではなく throw(:abort) を使う。
after_save での例外
class User < ApplicationRecord
after_save :notify_admin
private
def notify_admin
AdminMailer.user_created(self).deliver_now
# ↑ ここで例外が出ると…
end
end
user.save
# => Net::SMTPError等 が propagate される(save が rescue しない)
after_save で例外が出るとそのまま伝搬。save 戻り値では捕捉できないので注意。
トランザクション内での挙動
トランザクションの基本
ActiveRecord::Base.transaction do
user.save!
account.save!
# 両方成功なら commit、片方失敗で rollback
end
save vs save! でのトランザクション挙動
save の場合(暗黙トランザクションなし)
ActiveRecord::Base.transaction do
user.save # 失敗しても false が返るだけ
account.save # こちらは成功
# → user は保存されていない、account は保存される
end
save だけだと整合性が崩れる可能性。
save! の場合
ActiveRecord::Base.transaction do
user.save! # 失敗で RecordInvalid → トランザクション rollback
account.save! # 実行されない
end
# → 両方とも保存されない(整合性保持)
推奨パターン
ActiveRecord::Base.transaction do
user.save!
account.save!
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error e.message
# トランザクションは既に rollback されている
end
明示的な rollback
ActiveRecord::Base.transaction do
user.save!
raise ActiveRecord::Rollback if some_condition
account.save!
end
ActiveRecord::Rollback は例外を再発生させずに rollback だけ実行。
ネストしたトランザクション
ActiveRecord::Base.transaction do
user.save!
ActiveRecord::Base.transaction(requires_new: true) do
# ネストしたトランザクション(SAVEPOINT 使用)
account.save!
rescue ActiveRecord::RecordInvalid
# ネスト内だけ rollback
end
# ここに続く処理
end
使い分け指針
Controller での使い分け
class UsersController < ApplicationController
# ✅ フォーム送信 → save(戻り値で分岐)
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render :new, status: :unprocessable_entity
end
end
# ✅ API モード → save!(rescue_from で統一処理)
# rescue_from ActiveRecord::RecordInvalid, with: :render_invalid
end
Service Object での使い分け
class UserSignupService
def call(params)
user = User.new(params)
if user.save
UserMailer.welcome(user).deliver_later
[:ok, user]
else
[:error, user.errors.full_messages]
end
end
end
または例外パターン:
class UserSignupService
def call(params)
user = User.create!(params)
UserMailer.welcome(user).deliver_later
user
end
end
# 呼び出し側
begin
service.call(params)
rescue ActiveRecord::RecordInvalid => e
# ...
end
Job での使い分け
class ProcessUserJob < ApplicationJob
retry_on ActiveRecord::RecordInvalid, wait: 5.seconds
def perform(user_id)
user = User.find(user_id)
user.update!(status: :processed)
# save! で例外発生 → 自動リトライ
end
end
Job では save! 推奨。失敗を例外で確実にキャッチしてリトライ機構を活用。
詳細はSolid Queue 使い方の記事も参照。
rake task での使い分け
# lib/tasks/users.rake
namespace :users do
task migrate_data: :environment do
User.find_each do |user|
user.update!(processed: true)
# save! で失敗を即座に通知(ログ + 中断)
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error "Failed for user #{user.id}: #{e.message}"
end
end
end
詳細はrake task 作り方の記事も参照。
テストでの使い分け
RSpec.describe User do
it "creates valid user" do
user = User.new(valid_attrs)
expect(user.save).to be true
end
it "raises on invalid" do
user = User.new(invalid_attrs)
expect { user.save! }.to raise_error(ActiveRecord::RecordInvalid)
end
end
テストデータ作成は create! 推奨(失敗を即発見):
# ✅ 失敗を即発見
let(:user) { User.create!(valid_attrs) }
# ❌ 失敗を見逃しがち
let(:user) { User.create(valid_attrs) }
エラーハンドリングのベストプラクティス
API モード:rescue_from で統一
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordInvalid do |e|
render json: {
error: "validation_failed",
details: e.record.errors.as_json
}, status: :unprocessable_entity
end
rescue_from ActiveRecord::RecordNotFound do |e|
render json: { error: "not_found" }, status: :not_found
end
end
class Api::UsersController < Api::ApplicationController
def create
user = User.create!(user_params)
render json: user, status: :created
end
end
詳細はActiveRecord::RecordNotFound の記事。
Form Object パターン
class UserSignupForm
include ActiveModel::Model
attr_accessor :name, :email, :password
validates :name, presence: true
validates :email, presence: true, format: URI::MailTo::EMAIL_REGEXP
validates :password, length: { minimum: 8 }
def save
return false unless valid?
ActiveRecord::Base.transaction do
user = User.create!(name: name, email: email)
Account.create!(user: user, password: password)
end
true
rescue ActiveRecord::RecordInvalid
false
end
end
Result オブジェクトパターン
class Result
attr_reader :data, :error
def initialize(data: nil, error: nil)
@data = data
@error = error
end
def success?
@error.nil?
end
def self.ok(data) = new(data: data)
def self.fail(error) = new(error: error)
end
class CreateUserService
def call(params)
user = User.create!(params)
Result.ok(user)
rescue ActiveRecord::RecordInvalid => e
Result.fail(e.record.errors.full_messages)
end
end
# 呼び出し側
result = CreateUserService.new.call(params)
if result.success?
redirect_to result.data
else
render :new, locals: { errors: result.error }
end
ありがちな間違い
1. save の戻り値を見ない
# ❌ 失敗を見逃す
user.save
redirect_to user_path(user) # user.id は nil!
# ✅
if user.save
redirect_to user_path(user)
else
render :new
end
または save! で確実に例外化:
user.save! # 失敗なら例外で通知
redirect_to user
2. トランザクション内で save(!なし)
# ❌ 整合性崩壊
ActiveRecord::Base.transaction do
user.save # 失敗してもrollback されない
account.save
end
# ✅ save! でロールバック保証
ActiveRecord::Base.transaction do
user.save!
account.save!
end
3. RecordInvalid を rescue StandardError で
# ❌ 範囲広すぎ
begin
user.save!
rescue StandardError => e
# DB接続エラーまで捕捉してしまう
end
# ✅ 具体的な例外を指定
begin
user.save!
rescue ActiveRecord::RecordInvalid => e
# バリデーションエラーのみ
end
4. update_attribute で意図せずバリデーションスキップ
# ❌ バリデーションスキップ(危険)
user.update_attribute(:email, "")
# ✅ バリデーション実施
user.update(email: "") # false が返る
user.update!(email: "") # 例外
5. before_save で return false(Rails 5+)
# ❌ Rails 5+ では効かない
class User < ApplicationRecord
before_save :check
def check
return false if blocked?
end
end
# ✅ throw(:abort)
class User < ApplicationRecord
before_save :check
def check
throw(:abort) if blocked?
end
end
6. after_save で例外をスロー
class User < ApplicationRecord
after_save :notify
def notify
raise "Failed" if some_condition
# ↑ save! でも save でも例外が伝搬
end
end
after_* コールバック内の例外は save の戻り値で捕捉できない。設計時注意。
7. errors を確認しない
# ❌ なぜ失敗したか不明
user.save
puts "failed" unless user.persisted?
# ✅ エラー情報を確認
user.save
unless user.persisted?
puts user.errors.full_messages
end
8. valid? と save の重複呼び出し
# ❌ バリデーションが2回走る
if user.valid?
user.save
end
# ✅ save が valid? を内部で呼ぶ
if user.save
# ...
end
valid? / errors の活用
valid? で事前チェック
user = User.new(email: "")
user.valid?
# => false
user.errors.full_messages
# => ["Email can't be blank"]
save を呼ばずにバリデーションだけ走らせたい時に。
errors の構造
user.errors.full_messages
# => ["Email can't be blank", "Name is too short"]
user.errors[:email]
# => ["can't be blank"]
user.errors.details
# => { email: [{ error: :blank }] }
user.errors.size
# => 2
user.errors.empty?
# => false
カスタムエラー追加
class User < ApplicationRecord
validate :check_quota
private
def check_quota
if User.count >= 1000
errors.add(:base, "登録上限に達しました")
end
end
end
:base は特定カラムに紐付かないエラー。
関連メソッド早見表
| メソッド | 用途 | バリデーション |
|---|---|---|
save | 保存(new/update両用) | 走る |
save! | 保存、失敗で例外 | 走る |
save(validate: false) | バリデーションスキップ保存 | 走らない |
create | new + save の一括 | 走る |
create! | 失敗で例外 | 走る |
update | 属性更新 + 保存 | 走る |
update! | 失敗で例外 | 走る |
update_attribute | 単一属性更新(検証スキップ) | 走らない |
update_columns | DB直接更新 | 走らない |
update_column | 単一カラムをDB直接 | 走らない |
touch | updated_at 更新 | 走らない |
valid? | バリデーションのみ | 走る |
invalid? | valid? の逆 | 走る |
destroy | 削除 | コールバック走る |
destroy! | 失敗で例外 | 同上 |
delete | DB直接削除(コールバックスキップ) | 走らない |
⚠️ update_attribute / update_columns / update_column / delete はバリデーション/コールバックをスキップするため、業務コードでは慎重に。
よくある質問(FAQ)
Q1. save と save! どちらを使うべき?
| 状況 | 推奨 |
|---|---|
| フォーム送信 | save(戻り値で分岐) |
| トランザクション内 | save!(自動rollback) |
| API(rescue_from統一) | save! |
| Service Object | チームの方針次第 |
| Job/Worker | save!(リトライ機構活用) |
| rake task | save!(失敗即発見) |
| テストデータ作成 | create!(バグ早期発見) |
Q2. RecordInvalid のメッセージカスタマイズ
class User < ApplicationRecord
validates :email, presence: { message: "は必須です" }
end
begin
User.create!(email: "")
rescue ActiveRecord::RecordInvalid => e
e.message
# => "Validation failed: Email は必須です"
end
i18n 対応:
# config/locales/ja.yml
ja:
activerecord:
errors:
models:
user:
attributes:
email:
blank: "を入力してください"
Q3. save(validate: false) はいつ使う?
# バリデーションスキップ
user.save(validate: false)
主な用途:
- 既存データのマイグレーション
- レガシーデータの段階移行
- 内部処理で意図的にスキップ
⚠️ 通常の業務コードではほぼ使わない。
Q4. save! の例外を rescue すべきか
ケースバイケース:
# 上位で rescue されるなら下位では何もしない
class Service
def call
user.save! # 例外そのまま伝搬
end
end
# controllerで rescue_from
class UsersController < ApplicationController
rescue_from ActiveRecord::RecordInvalid do |e|
render json: { errors: e.record.errors }, status: 422
end
end
Q5. update_columns との違い
# save / update: バリデーション・コールバック走る
user.update(name: "")
# => false(バリデーション失敗)
# update_columns: 直接UPDATE、検証なし
user.update_columns(name: "")
# => true(強制的に保存)
update_columns は緊急時のデータ修正等限定用途。
Q6. トランザクションの自動 rollback 条件
トランザクション内で例外が出ると自動 rollback:
ActiveRecord::Base.transaction do
user.save! # RecordInvalid なら rollback
raise "error" # 任意の例外も rollback
end
例外なしで終了すると commit。
Q7. save! が成功するか確認したい
# valid? で事前確認
if user.valid?
user.save!
else
# エラー処理
end
# または rescue
begin
user.save!
rescue ActiveRecord::RecordInvalid
# ...
end
Q8. 既存レコードの save とは
user = User.find(1)
user.name = "Updated"
user.save
# UPDATE users SET name = 'Updated' WHERE id = 1
save は新規/既存両方対応。new_record? で判定。
Q9. save の前後にロジック
class User < ApplicationRecord
before_save :normalize
after_create :send_welcome
after_update :log_change
after_destroy :cleanup
private
def normalize
self.email = email.downcase if email.present?
end
end
before_* / after_* の活用。
Q10. save 後のエラーチェック
user.save
if user.persisted? && user.errors.empty?
# 成功
else
# 失敗
end
通常は if user.save で十分。
Q11. ネストした関連保存
class User < ApplicationRecord
has_many :posts
accepts_nested_attributes_for :posts
end
user = User.new(name: "Alice", posts_attributes: [
{ title: "Post 1" },
{ title: "Post 2" }
])
user.save # user と posts を一括保存
# 失敗時
user.errors # user のエラー
user.posts.first.errors # 個別の post のエラー
Q12. saveメソッドの内部動作
# ActiveRecord::Validations#save の概要
def save(**options)
perform_validations(options) ? super : false
end
def save!(**options)
perform_validations(options) ? super : raise_validation_error
end
save がバリデーション失敗で false を返し、save! が例外を投げる。本質は同じロジック。
参考リンク・関連資料
Rails 公式
- Active Record Validations(Guide) – バリデーション全般
- Active Record Callbacks(Guide) – コールバック
- ActiveRecord::Validations(API) – save/save! API
- ActiveRecord::Persistence(API) – 永続化メソッド
関連記事(本サイト)
- find vs find_by vs where 違い – 検索メソッドの基礎
- includes vs preload vs eager_load 違い – N+1問題
- ActiveRecord::RecordNotFound – find系エラー
- undefined method nil:NilClass – save失敗後のnil問題
- ActiveRecord::PendingMigrationError – DB状態
- rails db:migrate 使い方 – スキーマ
- rails console 使い方 – 動作確認
- rails generate 使い方 – model 生成
- rake task 作り方 – バッチ処理での保存
- Solid Queue 使い方 – Job でのエラー処理
- Rails 8 アップグレードガイド – 全般
まとめ
save / save! の違いを理解することは、Rails 開発の基礎中の基礎。要点を再整理します。
- save: 失敗で
falseを返す(戻り値で判定) - save!: 失敗で
ActiveRecord::RecordInvalid例外 - 同じパターン:
create/create!、update/update!、destroy/destroy!
使い分け
# フォーム送信 → save
if @user.save
redirect_to @user
else
render :new
end
# トランザクション内 → save!
ActiveRecord::Base.transaction do
user.save!
account.save!
end
# API → save! + rescue_from
class ApplicationController < ActionController::API
rescue_from ActiveRecord::RecordInvalid do |e|
render json: { errors: e.record.errors }, status: 422
end
end
避けるべきメソッド(バリデーションスキップ)
update_attributeupdate_columnsupdate_columndelete
特別な理由がない限り save / save! / update / update! を使用。
コールバック
before_*/after_*で前処理・後処理throw(:abort)で halt(Rails 5+)after_*での例外は伝搬する
トランザクション
save!で自動 rollbackActiveRecord::Rollbackで例外なし rollback
これらの知識は、Rails アプリの設計・エラーハンドリング・トランザクション管理など、あらゆる場面で活用できます。本記事をブックマークしておけば、save / save! の選択に迷うことが大幅に減ります。
本記事は2026年6月時点の情報をもとに、Ruby on Rails 7.x / 8.x での動作確認・公式ドキュメントに基づき作成しています。Rails のバージョンによって挙動が異なる場合があるため、最新の情報はRails公式ガイドもあわせてご確認ください。
-
前の記事
Linux unzipコマンドで展開先ディレクトリを指定する方法|オプション一覧と実用例を徹底解説 2026.06.26
-
次の記事
Linuxでプロセスをバックグラウンド実行する方法|nohup・&・disown完全ガイド 2026.06.27
コメントを書く