AWDwR "Chapter17 Action View" つづきのつづきのつづき
Chapter17つづき、いきますよ。
Layouts and Components
ビューにもDRY原則に則って重複を避けるためのレイアウト、パーシャルズ、コンポーネントという仕組みがある。
まずはレイアウト。レイアウトのテンプレートは以下のような感じ。
<html> <body> <%= @content_for_layout %> </body> </html>
ミソは@content_for_layoutで、アクションでレンダリングされた結果がセットされ、レイアウトの中でそれが表示される。
レイアウトのテンプレートファイルはコントローラ名がstoreの場合、デフォルトではapp/views/layout/store_layout.[rhtml|rxml]になる。またapplication.[rhtml|rxml]というテンプレートファイルを用意しておくと対応するテンプレートがないコントローラに適用される。
デフォルトのテンプレート以外を使いたい場合はコントローラクラスの中で以下のように指定。
layout "standard" layout "standard", :except => [:rss, :atom] # 指定されたものには適用しない layout "standard", :only => [:foo, :bar] # 指定されたものだけに適用する
以下のようにすれば動的にレイアウトを変えることもできるし…
class StoreController < ApplicationController layout :determine_layout private def determine_layout (レイアウト名を返す) end end
アクションごとにレイアウトを指定することもできる。
def rss render(:layout => false) # レイアウトを使用しない end def checkout render(:layout => "layouts/simple") end
また、個々のアクションのテンプレートからレイアウトに対して値を渡すこともできる。
# レイアウト <html> <body> <h1><%= title %></h1> </body> </html> # 個々のアクションのテンプレート <%= @title="Hello" %> # @titleがレイアウトに渡る
ページの一部分をテンプレートにしておいて、テンプレート内からそのテンプレートを呼ぶことができる。この一部分のテンプレートのことをパーシャルズ(?)といって、ファイルの名前は_で始める。例えば_article.rhtmlというテンプレートを用意しておくと以下のようにしてテンプレートから呼ぶことができる。
<%= render(:partials => "article", :object => @an_article) %>
一覧表示みたいに繰り返して表示したい場合はパーシャルズを使って
<%= render(:partials => "article", :collection => @article_list) %>
とする。オプションに:spacer_templateというのを指定すると、間にはさむテンプレートを指定できる。
ビューやアクションの中でアクションを呼び出すのをコンポ−ネントというんだけど、コンポーネントはその名のとおりコンポーネント化できる。コンポーネントはcomponentsディレクトリ内にディレクトリを作ってその下にコントローラ、モデル、ビューなどを置いておく。
コンポーネントの呼び出し方は以下のようにディレクトリ付のコントローラを指定する。
<%= render_components(:controller => 'sidebar/link', :action => 'get_link') %>
コンポーネント用コントローラはこの場合sidebarディレクトリ以下に置いておく。
class Sidebar::LinkController < ActionController::Base uses_component_template_root Link = Struct.new(:name, :url) def self.find(*ignored) ... end def get_links ... end end
コンポーネント用コントローラが普通のコントローラと違う点は、モジュール内で定義されていること、uses_component_template_rootが宣言されていることの2つ。コンポーネント化しておけば、お友達がそれを気に入った場合そのコンポーネントのディレクトリを「はいっ」とあげることができるよ。
もう少し!