初めまして、久保雄貴と申します。
今回はrenderメソッドについて自分が知ったことについて書いてみようと思います。
間違っている点や「こういう風に書いたらいいよ」などアドバイスがありましたら、コメントください。
#renderメソッドについて
##1. レンダリングとは?
renderメソッドについて記述する前に、レンダリングという言葉について説明します。
レンダリングとは、ビューファイルから最終的にHTMLにコンパイルされたものをブラウザで読み込んで表示させる一連の流れのことを言います。
ビューファイルにはコードが書かれていますが、ただ文字列が並んでいるだけでそのまま表示してもただ文字が表示されるだけです。
しかし各ブラウザが、そのコードを読んでそのコード通りに表示画面を作成して表示してくれているのです。
ここで重要なのは、Ruby on Railsでは、コントローラーでアクションを起動して一連の動作を行った後、コントローラーと同じ名前のビューファイルを自動的にレンダリングしてくれるということです。
こちらで何か指示を書く必要はありません。
createアクションを起動
↓
メソッド内の命令を実行(自分で記述)
↓
create.html.erbをレンダリング(自動でするよう定義されている)
##2. renderメソッドとは?
renderメソッドとは、レンダリングする元のビューファイルを直接指定することができるメソッドです。
さて、復習ですが、Lesson7の作業中に「render」というメソッドを使いましたね。
何をしたかというと、
① 違うファイル(index.html.erb と show.html.erb)に書かれている全く同じコード切り取る。
② 新しく作ったファイルにペーストする。
③ 使いたいファイルの中でrenderメソッドを使って呼び出す。
というものでした。(部分テンプレートの実装)
renderメソッドを使うことで、指定した別のビューファイルを読み込んで実行してくれるわけです。
メリットとしては、同じコードを別のビューファイル(index.html.erb や show.html.erbとも違う)でも使用できることです。
その時の書き方は
<% render partial: "post", locals:{post: post}%> でした。
partial: → 部分テンプレートのファイル名を指定する
locals: → 部分テンプレートのファイルで使用したい変数を定義する(左側のpost)
しかし、renderメソッドはオプションを使うことでこの他にも使い方があるようです。
その一つが
render action: :アクション名
です。
例えば、トップページに行って欲しい場合、
render action: :index
と記述します。
どういう時に使うかというと、
上に書いた通りRailsではデフォルトで、コントローラーと同じ名前のビューファイルをレンダリングしてくれるのですが、それをさせずに、こちらで指定した別のビューファイルを指定してレンダリングさせるように設定したい時です。
例えば、投稿フォーム(new.html.erb)のページで「タイトル」と「内容」を書いて、投稿ボタンを押すと、「投稿が完了しました。」と表示する、投稿完了ページ(create.html.erb)が表示されますね。
そうではなくて、トップページを表示したい時に使います。
どこに記述するかというと、コントローラー内のcreateアクションが定義されているところです。
このように記述するとcreateアクション内で、データベースに投稿内容が保存された後にトップページを表示してくれます。
##3. 疑問
さて、ピンときている方もいらっしゃるかもしれませんが、私たちは、すでに自動的にレンダリングをさせずに、トップページを表示させる方法を学んでいます。
redirect_toメソッドです。
redirect_to '/' (もしくは root_path)
と記述するとトップページを表示してくれます。
ここで疑問です。
redirect_to メソッド
render action: メソッド
を使うと、それぞれどのような動き、結果になるのでしょうか。
4. 実験
今回は、以下のようにcreateアクション内に両方を記述して、動きを見てみましょう。
def create
Post.create(post_params)
redirect_to root_path
end
def create
Post.create(post_params)
render action: :index
end
- redirect_to メソッドの場合
- render action: メソッドの場合
内容は、
「eachメソッドを起動しようとしたら、インスタンス変数@postの中身がnilになっていて使えません。」
ということです。
ここで、index.html.erbを見てみましょう。
確かに、@postの中身をeachメソッドを使って内容を表示させてますね。 ではこの@postはどこで定義されているかというと、def index
@post = Post.all
end
ここです。
postscontrollerのindexアクション内です。
##5. 4.の実験でわかったこと
-
redirect_toメソッド
ルーティングにリクエストを送り、postsコントローラーのindexアクションを起動させるため、@postの中にデータベースの内容がコピーされる。その後、index.html.erbがレンダリングされる。
結果として、トップページが表示される。 -
render action: :index
ルーティングを介さずに直接index.html.erbを指定してレンダリングするため、index.html.erb内の@postの中身がからのままになっている。(@postに渡すインスタンス変数をcreateアクションが持っていない。)
結果として、エラーが表示される。
6. 結論
render action:メソッドでトップページを表示させることはできるが、トップページの内容が書かれた、ビューファイル(index.html.erb)にインスタンス変数がある場合はそのインスタンス変数をなんとかしてあげないと、エラーが起こる。
何か特別な事情がない限りredirect_toを使った方がいいのかな?と思いました。
何か、特別な恩恵をうける場面があれば教えてもらえると勉強になります。
*** P.S. ちなみに、こうすると、トップページを表示できます。
無駄な記述ですね。
ということで、初投稿は以上です。
ありがとうございました。
<参考>