讃岐小僧のEngineering×Techメモ

未経験から挑戦中のプログラミングや、趣味の野球や狩猟について、その他、ビジネスやテクノロジーをテーマに様々なことをつぶやく場所です。

【Rails】Template, Layout, Partialについて簡易に整理してみた

Templates、Partials、Layoutについて

Railsのテンプレートは様々なテンプレート形式をサポートしているらしいですが今回はおなじみの「.erb」について記載します。

「.erb」ファイルの場合、Railsでは<% %>タグと<%= %>タグをサポートする。 <% %>はループやブロックを利用する際に利用し、<%= %>は何かしらのアウトプットをしたいときに利用する。

<%= %>を使ってみる

class ClientController < ApplicationController
  def index
    @clients.all
  end
end

この時、@clientsにはselect * from clientsの戻り値が格納されていると思っていいです。 また、この時にindexアクションのviewに以下のように記述するとコントローラーで@clientsに格納したデータのnameカラムの一覧をViewに表示させることができる。

<ul>
 <li>
  <%= @clients.each do |client| %>
   <p> client.name </p>
  <% end %>
 <li>
<ul>

同一Contoroller内でActionViewをRenderする

アクション名とは異なるテンプレートを表示させたい場合の例。

def update
  @book = Book.find(params[:id])
  if @book.update(book_params)
    redirect_to(@book)
  else
    render "edit"
  end
end

Updateメソッドの呼び出しに失敗した場合に、BooksControllerのeditアクションのView(edit.html.erb)ファイルを呼び出します。

別のcontrollerからActionViewを表示させる

ProductControllerのshowアクションのView(show.html.erb)を表示する

render "products/show"       

rederしていることを明示的に記載したい場合は下記のようにも記述できる

render template: "products/show"       

レイアウトの検索順序

Railsはレイアウトを探索する場合、最初に現在のコントローラと同じ基本名を持つレイアウトがapp/views/layoutsディレクトリにあるかどうかを調べます。たとえば、PhotosControllerクラスのアクションから出力するのであれば、app/views/layouts/photos.html.erbを探します。 該当のコントローラに属するレイアウトがない場合、app/views/layouts/application.html.erbを使用します。

コントローラーのレイアウトを指定する

プロダクトコントローラーの中でインベントリーレイアウトを指定しています。 この宣言によって、ProductsControllerからの出力で使用されるレイアウトはapp/views/layouts/inventory.html.erbになります。

class ProductsController < ApplicationController
  layout "inventory"
  #...
end

アプリケーション全体で特定のレイアウトを使用する

アプリケーション全体で特定のレイアウトを使用したい場合は、ApplicationControllerクラスでlayoutを宣言する。

class ApplicationController < ActionController::Base
  layout "main"
  #...
end

この宣言によって、アプリケーションのすべてのビューで使用されるレイアウトはapp/views/layouts/main.html.erbになります。

レイアウトの継承

レイアウト宣言は下の階層に継承されます。

(application_controller.rb)

class ApplicationController < ActionController::Base
  layout "main"
end
(posts_controller.rb)

class PostsController < ApplicationController
end
(special_posts_controller.rb)

class SpecialPostsController < PostsController
  layout "special"
end
(old_posts_controller.rb)

class OldPostsController < SpecialPostsController
  layout false
 
  def show  
    @post = Post.find(params[:id])
  end
 
  def index
    @old_posts = Post.older
    render layout: "old"
  end
  # ...
end

①ビューの出力には基本的にmainレイアウトが使用されます。 ②PostsController#indexではmainレイアウトが使用されます。 (継承している) ③SpecialPostsController#indexではspecialレイアウトが使用されます。(定義している) ④OldPostsController#showではレイアウトが適用されません。 (falseを宣言している) ⑤OldPostsController#indexではoldレイアウトが使用されます。(indexアクションでoldが定義されている)

renderとredirect_toの違い

redirect_toを実行した後、コードはそこで実行を終了し、ブラウザからの次のリクエストを待ちます (通常のスタンバイ状態)。 その直後、redirect_toでブラウザに送信したHTTPステータスコード302に従って、ブラウザから別のURLへのリクエストがサーバーに送信され、サーバーはそのリクエストを改めて処理します。

Renderの場合はサーバーに対して新たなリクエストを送ることなくViewをレンダーするのでサーバブラウザ間のやり取りを減らすことができます。

部分テンプレートを利用する

(index.html.erb)

<%= render "menu" %>

この場合はapp/views//_menu.html.erbを呼び出しています。 また同一フォルダ内に格納していない部分テンプレートを表示させる場合下記のように記載する。

(index.html.erb)
<%= render "shared/menu" %>

この場合は下記パスのapp/views/shared/_menu.html.erbを表示させる

Partialオプション

<% @products.each do |product| %>
<%= render partial: "product" , locals: {product : product}

eachメソッド内のproduct変数が部分テンプレート(_product.html.erb)内でproductという変数として利用できる

下記の場合

<% @products.each do |product| %>
<%= render partial: "product" , locals: {product_partial : product} %>

eachメソッド内のproduct変数が部分テンプレート(_product.html.erb)内でproduct_partialという変数として利用できる。

以上です。