@yosaku_ibs

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

【Rails】 「if @user.save」というコードの挙動について

Q&A

Closed

解決したいこと

このコードでは@userのインスタンスを生成したあとに、「@user.saveメソッド」が実行されていないのに、なぜ登録が完了するのでしょうか?

(ひょっとしてifの後に書かれている「@user.save」でデータベースへの登録が実際に完了してしまうのでしょうか?)

ソースコード

def create
    user_params = params.require(:user).permit(:name, :email, :password,
    :password_confirmation)
    @user = User.new(user_params)
    if @user.save
        flash[:notice] = "登録しました"
        # どこかへリダイレクト
    else
        flash.now[:alert] = "登録に失敗しました"
        render "new" end
    end

end

自分で試したこと

検索しましたが解決に繋がるヒントにたどりつけませんでした。

以上、お手数ではございますが
もしご存知の方がいらっしゃいましたら
ご教示の程よろしくお願い申し上げます。

0 likes

3Answer

Comments

  1. @yosaku_ibs

    Questioner

    @yulianess23様

    はじめまして。お世話になります。
    ご回答くださり誠にありがとうございます。
    ご紹介くださった記事は既に確認したのですが
    納得ができない状況でございまして...。

    あくまでも条件式の部分に書かれたコードはtrueかfalseかを評価するための
    ものなので、データベースに登録するのならtrueの場合に実行する処理の部分に@user.saveが記述されているべきなのではないかと思ってしまいます。(下のコードのご参照をお願い致します。)


    ```
    if @user.save
    @user.save
    flash[:notice] = "登録しました"
    # どこかへリダイレクト
    else
    flash.now[:alert] = "登録に失敗しました"
    render "new" end
    end
    ```

    trueの場合に実行する処理の部分に@user.saveを記述しなくてもいい理由が
    知りたいのですが、@yulianess23様ご解説くださいませんでしょうか??

  2. @obsidian_puyo さんが回答しているように、
    「条件式にメソッドを入れると、そのメソッドが実行されてその戻り値が評価されます。」
    これはRubyでも同様です。

    .saveは、簡単に言えば
    「DB登録をして、その結果が成功ならtrue、失敗ならfalseを返す」
    というメソッドになります。

    なので、「if @user.save」に入った時点でDB処理がされ、
    もし成功した場合は「if true」と同じ評価になりますし、
    失敗していれば「if false」と同じ評価になります。

    if文なので
    「DB登録をしたら成功するのでtrueのルートにいってね」
    という仮定で行っている感じもするのですが、
    実際は本当にDB登録をして、その結果を返しているのです。

    どちらかといえば
    「DB登録したら成功したよ!だからtrueのルートにいってね!」
    という感じです。
  3. @yosaku_ibs

    Questioner

    @yulianess23

    いつも大変お世話になっております。
    条件式にメソッドを入れると実行されるのですね!
    かつ今回の場合はDBに登録されているとのことで
    納得できました!!
    ご丁寧にご対応くださり誠にありがとうございました。

基本的にプログラミング言語では条件式にメソッドを入れると、そのメソッドが実行されてその戻り値が評価されます。
rubyには明るくないのですがsaveメソッドの戻り値は保存に成功したか否かを返すようです。

メソッドを評価するといっても実際に実行して戻り値が返ってこないと評価はできませんよね?
せっかく実行したのに元に戻したりはしないのでそのまま登録が完了してしまうのではないでしょうか。

以下Javaの話にはなりますが大抵のプログラミング言語で同じ動きをすると思います。

1Like

Comments

  1. @yosaku_ibs

    Questioner

    @obsidian_puyo様

    はじめまして。
    ご回答くださり誠にありがとうございます。
    条件式とは言っても、実際に実行されるのですね!
    学びになりました!

    Javaのリンクも併せて貼り付けて下さり誠にありがとうございます。
    このルールはJavaにも共通するルールだということも併せて頭に入れておきます。
    ありがとうございました!

データベースに登録するのならtrueの場合に実行する処理の部分に@user.saveが記述されているべきなのではないかと思ってしまいます。

「このifで判定しているのは何か」を考えてみてください。
ここで判定しているのは「userの保存が成功したか失敗したか」です。

if @user.saveという書き方が分かりにくいのであれば、下記のコードでどうでしょうか?

@isSeveSuccessed = @user.save # userを保存する
if @isSeveSuccessed # userの保存が成功したか失敗したかを判定する
    # 成功した場合
    flash[:notice] = "登録しました"
    # どこかへリダイレクト
else
    # 失敗した場合
    flash.now[:alert] = "登録に失敗しました"
    render "new" end
end

成功の場合は次のような流れになります。

  1. userを保存する
  2. userの保存が成功したか失敗したかを判定する(成功した)
  3. 「登録しました」のメッセージ
  4. どこかへリダイレクト

trueの場合に実行する処理の部分に@user.saveを記述しなくてもいい理由

userの保存が成功しているのに、再度userの保存を行うことになるからです。

  1. userを保存する
  2. userの保存が成功したか失敗したかを判定する(成功した)
  3. userを保存する(2回目)
  4. 「登録しました」のメッセージ
  5. どこかへリダイレクト

あくまでも条件式の部分に書かれたコードはtrueかfalseかを評価するための
もの

if文としてはそうですが、その条件式は実行されます。
条件式を実行した結果が評価されると考えてください。
次の結果はどちらも同じです。

def equalZero(num)
    return num == 0
end

@num = 0

if @num == 0
    puts 'numは0です'
end

if equalZero(@num)
    puts 'numは0です'
end
0Like

Comments

  1. @yosaku_ibs

    Questioner

    @blue32a様

    はじめまして。お世話になります。
    ご回答くださり誠にありがとうございます。
    違った視点での解説ありがとうございます。
    参考にさせて頂きたいと思います。
    ありがとうございます。

Your answer might help someone💌