【Rails入門説明書】renderについて解説
はじめに
Railsの基本構造はMVC(Model、View、Controller)です。
このうち、ユーザーインターフェイスとなるViewは、見た目や動きの中心となる部分ですので、Railsアプリケーションの成否を分ける要とも言えます。
そのため、Viewは最後まで何度も修正することが多い部分でもあるのです。そうなると、いつの間にやら「同じようなプログラムコードの繰り返し」になってしまっていることが少なくありません。
同じコードの繰り返しになってしまうと、メンテナンス性や可読性が著しく下がりますので、できる限り避けなければいけません。
そんなときに活躍するのが、renderメソッドなのです。
今回は、Viewのプログラムコードをシンプルにして、メンテナンス性と可読性を飛躍的に上げてくれるrenderメソッドについて、詳しく解説します。
renderメソッドとは
冒頭で説明したとおり、renderメソッドは、Viewの表示内容を制御するメソッドです。
もっとも多い使い方としては、「部分テンプレート」と呼ばれる、「別に定義した表示内容」を好きなところに挿入して表示する方法でしょう。
この機能を使えば、View上の重複しているコードをなくし、全体をすっきりと見やすくすることができるのです。
具体的な構文は、以下のようになっています。
render 表示するRHTMLの名称 # (1)
render オプション # (2)
RHTMLの表示
(1)がもっとも単純な構文で、指定したRHTMLファイル(Railsでhtmlと解釈されるerbファイルなど)をrenderメソッドが記載されている箇所に読み込みます。
例えば、View内で以下のように使用することで、viewファイルと同じディレクトリにある「_head.html.erb」と「_foot.html.erb」を挿入することができるのです。
<p>
site body
</p>
<%= render ‘foot’%>
この例のように、renderは指定されたRHTMLの名称に「_」を付けたRHTMLファイルを読み込みますので、憶えておきましょう。
オプション
renderに設定できるオプションは、以下のようになっています。
オプション | 説明 | 例 |
---|---|---|
:action | アクション名で指定する他のアクションのテンプレートを表示する | render :action => “new” →newアクション用のRHTMLを表示する |
:partial | 「部分テンプレート」を表示する 引数を渡すことも可能 | render :partial => “category” →_category.rhtmlを表示する render :partial => “category”, :locals => { :v1 => xxx, :v2 => xxx } →ローカル引数を渡す |
:template | テンプレートを直接指定して表示する | render :template => “user/new” →userの_new.html.erbを表示 |
:file | ファイルパスを直接指定して表示する | render :file => “shared/user/page” →Railsアプリケーション管理外のファイルpageを表示する |
:plain | 任意の文字列を表示する ※5.1未満では:text | render :plain => “Hello Rails!” →Hello Rails!と表示する |
:xml | 指定された文字列やモデルを表示する(コンテンツタイプをapplication/xmlに設定する) | @users = User.all render :xml => @users →usersテーブルをXMLで表示する |
:json | 指定された文字列やモデルを表示する。(コンテンツタイプをtext/x-jsonに設定する) | @users = User.all render :xml => @users →usersテーブルをJSONの形式で表示する |
:inline | erbファイルに記載するプログラムコードを直接指定することで、その結果を表示する | render :inline => “<%= Time.now %>” →現在時刻を表示する |
:html | 指定したhtmlを挿入する ※5.1以降 | render html: helpers.tag.strong(‘Not Found’) →太字の’Not Found’を表示する |
:js | 指定したvanilla Javascriptを挿入する ※5.1以降 | render js: “alert(‘Hello Rails’);” →Javascriptで’Hello Rails’と表示する |
:body | content typeの指定されていないコンテンツを挿入する ※5.1以降 | render body: “raw” →”raw”という文字列を表示する |
:nothing | なにも表示しない | render :status => 404 :nothing => true →なにも表示せず404エラーを返す |
以上のように、オプションを使用することで、より多彩な表示が可能になっています。また、以下のサブオプションを併用することで、より柔軟な表示が可能になっています。
サブオプション | 説明 | 例 |
---|---|---|
:layout | レイアウトを指定する レイアウトなしはfalseにする | render :action => “new” :layout => “user” →newアクション用のViewファイルをuserレイアウトで表示する |
:status | 返されるステータスコードを変更する | render :plain => “error” :status => 404 →errorと表示して404エラーを返す |
: content_type | コンテンツタイプを指定する ※5.1以降 | render file: filename, content_type: “application/css” →コンテンツタイプをCSSとしてブラウザに渡す |
:location | HTTPのLocationヘッダー(リダイレクト先のURL)を設定する ※5.1以降 | render :action => “new”, :location => users_url →新規作成画面のLocationヘッダーを一覧にする |
:format | Railsが使用するフォーマットを指定する デフォルトはhtml ※5.1以降 | render formats: :xml →Railsがxmlフォーマットを使用するように指定する |
なお、ほとんどの記載が「:オプション => 値」になっていますが、「オプション名: 値」でも同じ結果を得られます。
renderメソッドを使う上での注意点
renderメソッドは1度のアクションの中で2回以上呼び出されるとエラーになります。
じつは、コントローラーのアクションでは、renderメソッドが省略されていると解釈され、内部的に「app/views/コントローラ名/アクション名.html.erb」が表示されているのです。
そのため、アクション内で条件分岐などを利用してrenderメソッドを使う場合は、必ず「return」とセットにしておきしましょう。
render オプション and return
テスト環境の作成
ここ以降、実際に動かしながら学習していくため、テスト環境を構築しましょう。
余計な手間を省くため、scaffoldを使って環境を作っていきます。scaffoldの詳細は、「【Rails入門説明書】scaffoldについて解説」を参照してください。
コマンドプロンプトで以下のコマンドを順に入力してください。(render_testという名称にします)
[bash] rails new render_testcd render_test
rails generate scaffold User name:string age:integer
rails generate scaffold Item title:string price:integer
rake db:migrate
[/bash]
次にテスト用のデータを準備します。数が多いので、rails consoleを利用しましょう。
(こちらも、コマンドプロンプトで順に入力してください)
Item.create(title:”Wagyu”,price:2000)
Item.create(title:”Iwashi”,price:100)
Item.create(title:”Tomato”,price:100)
User.create(name:”Ryosuke”,age:18)
User.create(name:”Daigo”,age:23)
User.create(name:”Hiroshi”,age:35)
exit
[/bash]
以上で、テスト環境が整いました。
念のため、サーバーを起動して一覧を表示してみましょう。
[bash] rails s[/bash]
ブラウザから「localhost:3000/users」と「localhost:3000/items」にアクセスします。
renderメソッドの使い方(Viewで使う)
もっとも基本的なrenderメソッドの使い方が、Viewでの直接指定でしょう。
いくつか代表的なものを紹介します。
文字列表示
あまり使い勝手はないかもしれませんが、もっとも単純なrenderメソッドの使い方です。
Userの一覧ページ(localhost:3000/users)にメッセージを表示してみます。
(app/views/users/index.html.erb)
<h1>Users</h1>
<%= render :plain => “hogehoge” %> <!– (1) –>
<table>
<thread>
:
(1)の行を追加して、Userの一覧ページを読み込み直してみましょう。
少しわかりにくいので、赤枠で囲みましたが、「Users」というタイトルの下に「hogehoge」が表示されました。
partial
Viewでrenderを使う場合に、もっとも多いパターンがこの「partial」の表示でしょう。partialは、部分テンプレートと呼ばれるもので、まさにRHTMLの一部だけを切り取ったようなファイルです。
render :partial => 部分テンプレートファイル
上記のように指定することで、そのファイルを任意の位置に読み込むことができます。
以下のpartialファイルを作成して、保存しましょう。保存箇所は「app/views/shared/」です。(ディレクトリを追加してください)
(app/views/shared/_eol.html.erb)
End of List
</p>
この部分テンプレートをuser一覧のViewへ挿入してみます。以下の(2)を追記してください。
(app/views/users/index.html.erb)
</tbody>
</table>
<%= render :partial => “shared/eol” %> <!– (2) –>
<br>
<%= link_to ‘New User’, new_user_path %>
ここでも、赤枠で囲んでいる部分が、挿入された部分テンプレートです。
renderメソッドの使い方(コントローラーで使う)
次は、コントローラーで使ってみましょう。
こちらも、代表的なものをいくつか紹介します。
他のアクションのViewを表示する
Itemの新規作成ページに、Itemの1件目のデータを表示してみましょう。
コントローラーのnewアクションを以下のように修正します。
(app/controllers/items_controller.rb)
def new
# @item = Item.new # (1)コメントアウト
@item = Item.find(1) # (2)
render :action => “show” # (3)
end
もともとあった(1)はコメントアウトし、(2)(3)を追記します。
「localhost:3000/items」から「New Item」をクリックして「localhost:3000/items/new」にアクセスすると、
新規作成画面ではなく以下の1件表示画面になります。
ここで、ポイントは、(2)の@itemの代入文です。
renderメソッドは、あくまでも別のRHTMLを表示しているだけで、アクションが実行されるわけではありません。そのため、renderメソッドを使うだけでは、新規作成画面の表示に必要な@itemになにも格納されませんので、ここではfindメソッドを使って1件目のデータを取得しているのです。
他のコントローラーのアクションのViewを表示する
前述と同様ですが、Itemの画面でUserのデータを表示することもできます。
同じように、Itemコントローラーのnewアクションを修正します。
(app/controllers/items_controller.rb)
def new
# @item = Item.new # (1)コメントアウト
# @item = Item.find(1) # (2)
# render :action => “show” # (3)
@user = User.find(1) # (4)
render :template => “users/show” # (5)
end
先ほど追加した(2)(3)をコメントアウトし、(4)(5)を追記します。
他のコントローラーのViewを表示する場合は、actionオプションではなく、templateオプションを使います。また、取得しておくデータもUserモデルから取得しておかなければいけません。
JSON形式での出力
Webサービスへの応答などで、JSON形式で出力したい場合、renderメソッドで簡単に行えます。
Itemの一覧をJSON形式での出力に変更してみましょう。
ItemControllerのindexアクションに1行追記します。
(app/controllers/items_controller.rb)
def index
@items = Item.all
render json: @items # (6)
end
f
「localhost:3000/items」にアクセスすると、先ほどまでとは違って、JSON形式の文字列が表示されます。
renderとredirect_to
renderメソッドとよく似た動きをするメソッドとして、redirect_toメソッドがあります。
この2つは両方とも「指定したページを表示する」という表面上は同じ動きをしているように見えますので、よく混同されます。
しかし、実態は全然違っていますので、それぞれの動きを説明しておきましょう。
renderメソッド
表示する内容(テンプレートや文字列など)を指定します。
アクション名を指定することで、アクション名と同じViewファイルを使用してHTMLを作成するため、アクション自体を差し替えているように見えるが、表面上だけの変化なので、renderメソッドに指定したアクションに定義されている変数などは使えません。
そのため、表示しようとしているViewファイルで必要とする処理は、renderメソッドを実装しているアクション内で準備する必要があります。
redirect_toメソッド
ブラウザからのリクエスト(HTTPリクエスト+URL)を、redirect_toに指定されたリクエストとして実行されます。
つまり、redirect_toメソッドが実装されているアクションを実行すると、redirect_toメソッドに指定されているリクエストが、改めてroutes.rbによってルーティングされて、実行されるわけです。
そのため、redirect_toメソッドが実装されているアクションで定義されている変数は無効となって使うことができません。
まとめ
Railsのrenderメソッドについて、説明しました。
数多くのオプションがあり、表示上の処理を行うため、使用頻度が高いメソッドです。
しかし、表面上の動きに惑わされてしまうと、どうしてもうまくいかないこともありますので、実際にどう動いているのかをしっかりと理解して使用するようにしましょう。
・renderメソッドは、Viewに任意の表示内容を挿入することができる
・挿入するテンプレートを部分テンプレート(partial)と呼ぶ
・renderメソッドを使うことで、同じ表示の繰り返しをシンプルに実装できる
・renderメソッドでアクションを指定すると、そのアクション名と同じViewファイルが表示される
・renderメソッドは表示だけを指定するため、プログラムの動きとして、アクションが変更されているわけではない
・redirect_toメソッドは、別のアクションを実行し直す
【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。
「Rubyの学習がしたい。基礎をしっかりと理解したい」
「転職のサポートがほしい」
と考えている方はぜひお読み下さい。