Blank?=False

ゆるゆる仕事したいフリーランスエンジニアの記事

基礎RubyOnRails Chapter3-3 モックアップの作成

f:id:stonebeach-dakar:20160618082625p:plain

今回はレイアウトテンプレート、部分テンプレートについての解説回です。

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)

改訂3版基礎 Ruby on Rails (KS IMPRESS KISO SERIES)

レイアウトテンプレート

レイアウトテンプレートとは?

全体の枠となる部分。

Webページは、ある程度の共通性を持たせることで、操作しやすくなります。特に、データベースを使うWebアプリケーションでは、 全体的に似たレイアウトにすることで、目的のページにスムーズに行けるよう考えてデザインする必要があります。
本ブログを例に説明すると、
f:id:stonebeach-dakar:20160619213530p:plain

大きく分けて、ヘッダー部分、サイドバー部分、記事一覧部分に分かれています。
このうち、ヘッダー部分とサイドバー部分はどのページを開いても表示されるようになっています。
こういうどこに行っても表示される部分を定義するのがレイアウトテンプレートです。

もちろん、それぞれのページで別々に作ることもできますが、例えばサイドバーを表示させないようにしたい時、 いちいち全部のページのサイドバーを消さないといけません。面倒臭いよね。
こういうものは1つにまとめることで、メンテナンス性がよく、ソースコードが重複することを防ぐことができます。

デフォルトのレイアウトテンプレート

Rails newで新しくRailsアプリケーションを作成した時にデフォルトのレイアウトテンプレートが作成されます。
その内容は以下のようになっています。

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>Rails4book1</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>

内容としては、HTMLのヘッダーの定義をしているだけという感じ。
yield の部分に各アクションのテンプレートが埋め込まれるわけです。

このレイアウトテンプレートがレンダリングされると、以下のようなHTMLソースになります。
stylesheet_link_tagjavascript_include_tagヘルパーメソッドがレンダリングされています。

<!DOCTYPE html>
<html>
<head>
  <title>Rails4book1</title>
  <link rel="stylesheet" media="all" href="/assets/application.self-e80e8f2318043e8af94dddc2adad5a4f09739a8ebb323b3ab31cd71d45fd9113.css?body=1" data-turbolinks-track="true" />
  <script src="/assets/jquery.self-660adc51e0224b731d29f575a6f1ec167ba08ad06ed5deca4f1e8654c135bf4c.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/jquery_ujs.self-e87806d0cf4489aeb1bb7288016024e8de67fd18db693fe026fe3907581e53cd.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/turbolinks.self-c37727e9bd6b2735da5c311aa83fead54ed0be6cc8bd9a65309e9c5abe2cbfff.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/application.self-3b8dabdc891efe46b9a144b400ad69e37d7e5876bdc39dee783419a69d7ca819.js?body=1" data-turbolinks-track="true"></script>
  <meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="RPB3ht/EqiLtP/M3nNFSEy3PMATBXzexi9SyX1dcC4Oy1I+1Rhz6Tt+jlw3T+dgN10RAoK1ak7gE9SA5MkI6Uw==" />
</head>
<body>


</body>
</html>

レイアウトテンプレートの使用方法

よくある使用例として、Webページのタイトル文字列を設定があります。

application.html.erb

<省略>
<header>
  <title><%= page_title_%></title>
<省略>


application_helper.rb

<省略>
def page_title
  title = "SampleApp"
  title += " | " @page_title if @page_title
  title
end
<省略>

この処理を説明すると、@page_titleがnilであればデフォルトの"SampleApp"を表示し、内容があればその文字列と区切り線を"SampleApp"に 追加する、という動作になります。
こうすると、テンプレートで@page_titleを設定すればそれぞれのページに合わせたタイトル文字列とアプリケーションをRailsが自動的に設定してくれるようになります。

ヘッダー、サイドバー、ナビゲーションバー、等はレイアウトテンプレートで定義することもできますが、部分テンプレートとして作成したほうが、それぞれの部品が独立するためメンテナンスしやすくなります。

レイアウトテンプレートの切り替え

コントローラ、アクションによってはデフォルトとは別のレイアウトテンプレートを使用したいということもあると思います。
例えば、管理者ユーザは管理用のバーを表示するが、標準ユーザーは表示しない、等、ユーザーによって表示するものを変える時です。

レイアウトテンプレートの指定方法は、以下の3通りあります。

  • apps/views/layouts/◯◯_html.erb(◯◯はコントローラ名)を作成する。
  • Controllerでlayoutsメソッドを使う。
  • アクション内でrenderメソッドにlayoutオプションを付けてレイアウトを指定

Controllerでlayoutsメソッドを使うサンプル

class SampleController < ApplicationController
  layouts "foobar"


アクション内renderメソッドでレイアウトを指定するサンプル

def sample
  render layout: "foobar"
end


それぞれ、使用できる範囲が異なるので使いたいタイミングに合わせての使い分けになりそうです。
例えば、いちいち全部のアクションに`render layout:"するなら、コントローラのメソッドのlayoutsを使えばいいし、絶対このレイアウトと決まっているならコントローラ名のレイアウトテンプレートを作ってしまえばいいわけです。

おまけ

デフォルトのレイアウトを変えてしまいたい時は、ApplicationControllerクラスでlayoutsメソッドを使いレイアウトテンプレートを指定すれば、デフォルトが変わります。
もちろん、ApplicationControllerクラスを継承したコントローラでlayoutsメソッドを使えば指定したレイアウトテンプレートに変えることもできます。
もし全部のレイアウトそのものが変わるような動きの場合はApplicationControllerで指定してしまおう!

部分テンプレート

部分テンプレートとは?

共通する部分、つまりテンプレートの一部を部品化する、というもの。
ヘッダー、サイドバーはもちろん、ログイン画面、ユーザー入力、編集画面等共通性があるものを部品化することでソースコードの重複を防ぎ、メンテナンス性をよくすることができる。

部分テンプレートの作成方法

部分テンプレートは、先頭に_(アンダースコア)を付ける必要があります。
ファイル保存場所は基本的に部分テンプレートを使用するコントローラのフォルダ内app/views/◯◯(◯◯コントローラ名)になりますが、共用部品テンプレートとして別フォルダに保存することもできます。その場合は下記部分的テンプレートを異なるコントローラ間で共有するを参照してください。

部分テンプレートの呼び出し

たとえば、_Userform.html.erb という部分テンプレートが同じコントローラのフォルダにあったとします。
それを、Edit.html.erbというテンプレートで使いたいと思った時は、以下のようにコーディングします。

edit.html.erb

<省略>

<%= render "Userform" %>

<省略>

renderメソッドはコントローラもビューにもあるのですが、使い方が異なるので注意してください。ちなみに自分も最初混乱しました。

部分テンプレートへのパラメータ渡し

ここまでの話だけだと、「ん?部分テンプレートになにかパラメータは渡せないの?使いにくそう」なんて思うかもしれません。

f:id:stonebeach-dakar:20160621123524j:plain

いや戦闘力じゃないから。
もちろん、部分テンプレートにパラメータを渡すこともできます。
その場合、renderメソッドの引数としてパラメータを渡します。

Sample.html.erb

<省略>
<%= render "show" data: :Sample>
<省略>

こうすることで、パラメータとして渡された情報がローカル変数としてアクセスできるようになります。
_show.html.erb

<% data = :default  if data.nil? %>
<%= data %>

パラメータは、複数渡すことができるので、状態と情報の2つを渡す・・・ということもできます。
余りたくさんのパラメータを渡すようなら、もっと細かく部分化することを検討してもいいかもしれません。

ちなみに、アクションで定義したテンプレート変数(テンプレート内で使える@~から始まる変数)は、部分テンプレートでも使うことができます。
ただし、部分テンプレートと呼び出し元のテンプレートで同じテンプレート変数名じゃないと使えません。 そのため、部分テンプレートが呼び出し元をいちいち気にする必要がでてしまうので、ちょっと使いにくくなってしまいます。

というわけで、パラメータを渡すことで呼び出し元も部分テンプレートもWin-Winな関係を結ぶことができるのです。
(なんか違う)

部分テンプレートを異なるコントローラ間で共有する

異なるコントローラ間で似たような画面、例えばユーザーアカウントの編集、管理者アカウントの編集画面です。
ユーザーアカウントの編集はUserコントローラ、管理者アカウントの追加はAdminコントローラですが、画面は似たような感じになるとします。(名前、メールアドレス、パスワードの入力画面)

この似たたような部分を_form.html.erbという部分テンプレートにして、共有してみます。
ViewsディレクトリにはUser,Adminという2つのサブディレクトリがあるとします。
f:id:stonebeach-dakar:20160621131010p:plain
そこに、sharedというディレクトリを作成し、_form.html.erbという部分テンプレートを追加します。
f:id:stonebeach-dakar:20160621132808p:plain
そして、User/Adminコントローラからこの部分テンプレートを呼び出すときは、以下のようにrenderメソッドの引数の部分テンプレート名を、/views以降のディレクトリ名からのパスに設定します。

<省略>
<%= render "shared/form">
<省略>


こうすることで、部分テンプレートの共有ができるようになります。
実際のところ、User/Adminのどちらかに保存してそれをディレクトリ名を含めた部分テンプレート名で呼び出すことはできるのですが、 共有しているものははっきり共有しています!とわかりやすくするために共有用のフォルダを作っておくほうが、メンテナンスしやすいと思います。

部分テンプレートの保存先

部分テンプレートの保存先について、RubyOnRailsアプリケーションプログラミングでは以下の用に説明されているので紹介します。

通常は以下のようなルールに沿って、保存先フォルダを決める事を強くお勧めします。

用途 保存先フォルダ
特定のコントローラのみ共有 /views/コントローラ名
アプリケーション全体で共有 /views/application
リソースに強く関連づいた部品 /views/リソース名(複数形)

Ruby on Rails 4 アプリケーションプログラミング

Ruby on Rails 4 アプリケーションプログラミング


今回はSharedというディレクトリを共有に使いましたが、上記の様なルールでも良いと思います。
リソースに強く関連づいた部品については、ここでは取り上げないので気になる人はRubyOnRailアプリケーションプログラミングを買ってみてね(はーと そのうち記事に取り上げてみます。