こんにちは。プログラミングスクールHappiness Chainでメンターをしているryoです。
今回はスクールでsaveとcreate、create(save)とcreate!(save!)をどのように使い分けるのか、質問があったので、実際に実務でどのように使い分けているかお話しします。
saveとcreateの違いと、エラーハンドリングの方法
saveとcraeteの違いは、以下になります。
-
save
- newで作成したインスタンスを、DBに保存する
- 返り値として、
true
(DB保存成功)orfalse
(DB保存失敗)を返す
-
create
- インスタンス生成 + DB保存を一括で行う
- 返り値として、DB保存成功・失敗に関わらず、インスタンスを返す(違いとして、IDの有無)
-
共通点
- インスタンスのerrorsに、ActiveModel::Errorインスタンスが配列に格納される
上記を考慮すると、エラーハンドリングは以下になります。
- saveの場合
def create
@user = User.new(user_params)
if @user.save
# 成功の処理
else
flash[:alert] = @user.errors.full_messages.join("\n")
render :new
end
end
- createの場合
def create
@user = User.create(user_params)
if @user.id.present?
# 成功の処理
else
flash[:alert] = @user.errors.full_messages.join("\n")
render :new
end
end
createの場合は、idが存在するかどうかで 判断する必要があります。
個人的には、saveの方が、エラーハンドリングをする際に分かりやすい かなと思います。
create(save)とcreate!(save!)の違いと、エラーハンドリングの方法
実務では、create!をよく使うので、create!の方で説明します。
「!」を付ける場合と付けない場合の違いは、
失敗した場合に、例外処理を発生させるかどうか になります。
上記で記載したcreateの場合を、create!に書き直すと以下になります。
def create
@user = User.create!(user_params)
# 成功の処理
rescue => e
flash[:alert] = e.messages
render :new
end
ただ上記の場合だと、ちょっと分かりずらいと感じるかもしれないですし、
エラーが考えられる場合って、@user = User.create!(user_params)
の部分のみですので、
1レコードの作成・更新の場合は、「!」を付けないで記載する 方が、どこでエラーが発生するのか明示的で良いかなと思います。
逆に、2レコード以上の作成・更新がある場合は、transactionを考慮する必要があり、
ActiveRecord::Base.transaction
で括った処理で、例外処理が起こった場合に、 rollbackするので、
以下のように記載することができます。
def create
ActiveRecord::Base.transaction do
@user = User.create!(user_params)
@profile = @user.profile.create!(profile_params)
end
# 成功の処理
rescue => e
flash[:alert] = e.messages
render :new
end
もし、上記をcreateで書こうとした場合は、以下のようになります。
def create
ActiveRecord::Base.transaction do
@user = User.create(user_params)
raise @user.errors.full_messages.join("\n") if user.id.nil?
@profile = @user.profile.create(profile_params)
raise @profile.errors.full_messages.join("\n") if profile.id.nil?
end
# 成功の処理
rescue => e
flash[:alert] = e.messages
render :new
end
上記だと、成功したかどうかを条件分岐して、raiseを自分で書く必要があります。
ですので、2レコード以上の作成・更新がある場合は、create!(save!)を使う 方がすっきりします。
まとめ
- 1レコードの作成・更新は、saveを使う
- 2レコード以上の作成・更新は、create!を使う