ケース
- よくある作成処理で、画面遷移後にメッセージを表示したい。
結論
- メソッド引数に複数のハッシュを渡す場合は、最後の引数以外は{}で囲う必要があります。
- メソッドの第1引数にハッシュを渡す場合は、必ず()を付けてメソッドを呼び出す必要があります。
def create
@game = Game.new(game_params)
if @game.save
redirect_to({action: :index}, notice: '試合情報の作成に成功しました。')
else
render :new
end
end
※redirect_toと()の間にはスペースは入れられません。
失敗例
def create
@game = Game.new(game_params)
if @game.save
redirect_to action: :index, notice: '試合情報の作成に成功しました。'
else
render :new
end
end
実際に画面操作してみると、遷移後の画面にメッセージが表示されず(noticeを受けるように記述しているのに)、しかもURLが以下のようになっていました。
http://localhost:3000/games?notice=試合情報の作成に成功しました。
原因
ググりながら解決方法を見つけ、問題なく動くようになったのですが、原因はRubyの文法にありました。
プロを目指す人のためのRuby入門によると、メソッド引数にハッシュを渡す時のルールについて記載されていました。
Rubyでは「最後の引数がハッシュであればハッシュリテラルの{}を省略できる」というルールがあります。
失敗例のコードでは、{}を書いていなかったため、action: :index, notice: '試合情報の作成に成功しました。'
の部分でひとつのハッシュと見なされてしまいます。
今回、redirect_toには「アクション」と「notice」のふたつのハッシュを渡す必要があるため、そこで上手くいっていなかったということです。
さらに
解決はしたのですが、そこで私は
「じゃあこう書いたらどうなる?メソッド呼び出しの()って省略できるんじゃなかったっけ?」
と、以下のコードを書きました。
def create
@game = Game.new(game_params)
if @game.save
redirect_to {action: :index}, notice: '試合情報の作成に成功しました。'
else
render :new
end
end
すると、画面操作する前にRubyMineに怒られました(Eclipseでいうコンパイルエラーみたいな感じで赤くなる)。
そのまま画面操作するとエラーになるようです。
プロを目指す人のためのRuby入門を読み進めると、次のページに同じケースについて書いてありました(著者の方に先を読まれているw)。
おや、エラーが発生してしまいました。(少し中略)実はこれは、ハッシュリテラルの{}がブロックの{}だとRubyに解釈されたためです。
(中略)
というわけで、このようにメソッドの第1引数にハッシュを渡そうとする場合は必ず()を付けてメソッドを呼び出す必要があります。
なるほどですね。。。
ということでやはり、上述のあの書き方でないとダメということですね。勉強になります!