おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

controllerを少しだけスリムにするtips

(※12月の1日から25日まで、日替わりで Ruby の Tips を紹介するイベント、 Ruby Advent Calendar jp: 2009 の 12 日目です。昨日は id:ohac さんでした。明日はうづら(udzura) さんの予定です。)

Railsネタをひとつ書きたいと思います。

titleをviewで設定したい

ほとんどのRails使いの皆さんは、おそらく下記のようなlayoutを使うことでviewをDRYにしているのではと思います。

app/views/layouts/application.html.erb

<html>
  <head>
    <title>タイトル</title>
  </head>
  <body>
    <%= yield %><!-- ここを各viewファイルで定義する -->
  </body>
</html>

ですがこれだとタイトルが固定になってしまいますね。アクションごとにタイトルを変えようとすると、下記のように、タイトルをインスタンス変数にしてcontroller側で設定する方法が思いつきます。


app/views/layouts/application.html.erb

<html>
  <head>
    <title><%= @title %></title>
  </head>
  <body>
    <%= yield %><!-- ここを各viewファイルで定義する -->
  </body>
</html>

app/controllers/main_controller.rb

class MainController < ApplicationController
  def index
    @title = "hoge"
  end

  def show
    @title = "fuga"
  end
end

しかし、本来、ページごとのタイトルはviewで設定する方がMVC的によいのではないでしょうか。*1

そこでcontent_forですよ

そんな時のために、Railsにはcontent_forというメソッドが用意されています。このメソッドを使うと、引数に対応するyieldとブロックの戻り値が置き換わります。具体的には下記のように使います。

app/views/layouts/application.html.erb

<html>
  <head>
    <title><%= yield :title %></title><!-- viewで定義したcontent_for :titleのブロックの内容で置き換わる -->
  </head>
  <body>
    <%= yield %>
  </body>
</html>

app/views/main/index.html.erb

<% content_for :title do %>
hoge
<% end %>

これでviewでタイトルを設定することが出来ました*2。もちろんjavascriptやcssも同じように設定することが出来ます。これでcontrollerが少しすっきりしましたね!

*1:この例では省略していますが、タイトル以外にもjavascriptやcssを切り替えるための設定をcontrollerのインスタンス変数に書いている人も多いでしょう。

*2:実際はhelperにtitleメソッドなどを定義してその中に書いた方がいいと思います