さらなる高みへ -higher ground -

プログラミング学習の定着を狙いとしたアウトプット(独り言)をしてみるブログ

部分テンプレートを使う

ここでは部分テンプレートの役割や使い方を学習する。
使いこなすことでコードの量を減らせたり、エラーの発生を防げるようになるため活用できるようになる。

部分テンプレートを使う

ここまででコメントの機能まで作成することが出来た。
ここでは、以前書いたコードを「部分テンプレート」を利用して書き換えてみたい。
部分テンプレートは発展的ですが、役立つことが多いのでチャレンジしてみる。

まず、部分テンプレートとは何かを解説し、その後に実際に編集する。

部分テンプレート ビューを作成する際に同じようなレイアウトの部分が複数存在する場合がある。
例えば、Twitterを思い浮かべてみる。
Twitterでは複数のツイートが表示されているが、これらのHTML構造は全て同じである。
このような場合に同じHTML構造の部分を共通化することによって、無駄なくビューファイルを作成することが出来る
この共通化された部分を、 部分テンプレートという。
部分テンプレートを使用した場合、そのHTML構造を他のビューでも使いまわすことができるという利点も存在する。

また、部分テンプレートのファイル名は必ずアンダーバー「_」から始まる

部分テンプレート

Pictweetもツイートを複数表示している箇所があった。以下のツイートの一覧画面である。
この箇所を部分テンプレートに書き換えてみたい。

赤の枠で囲まれた部分がひとつのツイートで、この構造の繰り返しでツイートの一覧が出来ている。
ここでこの部分を別のファイルに切り出して、そのファイルを呼び出して使う。

https://tech-master.s3.amazonaws.com/uploads/curriculums//112fed686d5c3a1db06de054e5668f25.png

このページのビューファイル(tweets/index.html.erb)は以下のようになっている。
この中のeachメソッドで囲まれた3~28行目がひとつのツイートのテンプレートになっている。この部分を別のファイルに切り出す。

tweets/index.html.erb

<div class="contents row">
  <% @tweets.each do |tweet| %>
    <div class="content_post" style="background-image: url(<%= tweet.image %>);">
      <div class="more">
        <span><%= image_tag 'arrow_top.png' %></span>
        <ul class="more_list">
          <li>
            <%= link_to "詳細", tweet_path(tweet.id), method: :get %>
          </li>
          <% if user_signed_in? && current_user.id == tweet.user_id %>
            <li>
              <%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %>
            </li>
            <li>
              <%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
            </li>
          <% end %>
        </ul>
      </div>
      <%= simple_format(tweet.text) %>
      <span class="name">
        <a href="/users/<%= tweet.user_id %>">
          <span>投稿者</span><%= tweet.user.nickname %>
        </a>
      </span>
    </div>
  <% end %>
  <%= paginate(@tweets) %>
</div>

部分テンプレートを作成する

「app/views/tweets」フォルダに「_tweet.html.erb」ファイルを作成し、以下の記述を追加する。
tweets/_tweet.html.erb

<div class="content_post" style="background-image: url(<%= tweet.image %>);">
  <div class="more">
    <span><%= image_tag 'arrow_top.png' %></span>
    <ul class="more_list">
      <li>
        <%= link_to "詳細", tweet_path(tweet.id), method: :get %>
      </li>
      <% if user_signed_in? && current_user.id == tweet.user_id %>
        <li>
          <%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %>
        </li>
        <li>
          <%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
        </li>
      <% end %>
    </ul>
  </div>
  <%= simple_format(tweet.text) %>
  <span class="name">
    <a href="/users/<%= tweet.user_id %>">
      <span>投稿者</span><%= tweet.user.nickname %>
    </a>
  </span>
</div>

ここではコピー&ペーストのショートカットも使えるが、より作業がスムーズなカット&ペーストのショートカットを使ってみる。
カットとは選択した部分をコピーして削除することであり、command(ctrl) + xがショートカットキーになる。
あとはcommand(ctrl) + vを使って選択した部分を適切な場所に貼り付ける。

https://tech-master.s3.amazonaws.com/uploads/curriculums//ee41c3c3c46cdb6bb690d1aedeacc55e.gif

この_tweet.html.erbファイルがツイートひとつ分のHTML構造を表す部分テンプレートになる。 続いて、こちらの部分テンプレートを呼び出す。
そのためには、renderメソッドを利用する。

render

renderメソッドは、部分テンプレートを呼び出す際に利用するメソッドである。

render partialオプション

renderメソッドに :partialというオプションをつけることで、明示的に部分テンプレート名を指定し、部分テンプレートを表示することができる。
下の例では、_sample.html.erbという部分テンプレートを呼び出している。

[例]
render

  render partial: "sample"
render localsオプション

また、localsというオプションを用いると部分テンプレート内でその変数を使えるようになる。

[例]
render

  render partial: "sample", locals: { tweet: "hello!" }

これで部分テンプレート内においてhello! という文字列の代入されたtweetという変数が使えるようになる。
では、renderメソッドを利用して_tweet.html.erbを呼び出してみる。

index.html.erbを以下のように編集する。
tweets/index.html.erb

<div class="contents row">
  <% @tweets.each do |tweet| %>
    <%= render partial: "tweet", locals: { tweet: tweet } %>
  <% end %>
  <%= paginate(@tweets) %>
</div>

ここでのrenderメソッドのlocalsオプションに注目してみる。
{ tweet: tweet } の右側の tweet はeachメソッド内の変数としてのtweettweetインスタンスを示している。
一方、左側の tweet は部分テンプレート内での変数の名前を表している。

 <%= render partial: "tweet", locals: { tweet: tweet } %>

例えば

 <%= render partial: "tweet", locals: { partial_tweet: tweet } %>

と名前を変更すると、tweetというインスタンスを部分テンプレートの中ではpartial_tweetとして使えるということある。

その後サーバーを立ち上げた状態でツイートの一覧画面にアクセスすると、これまでと同様にツイートの一覧が表示されたら成功である。
※表示自体は変わらないため、エラーが起きなければ問題ない。

表示自体が変わらないにも関わらず、部分テンプレートを用いるのは繰り返し再利用出来るためである。

再利用できるメリットとして

・繰り返し書くコードを一回で済ます

・修正するときに修正箇所が少なく済むなどがある。

では、実際に先ほど作成した部分テンプレートを別の箇所にも適用させてみよう。
マイページの一覧画面を思い出してみると、ここにも部分テンプレートを適用出来る。

https://tech-master.s3.amazonaws.com/uploads/curriculums//3fa1a0727b26d5c4e194b087c0f58ae6.png

users/show.html.erbを以下のように編集する
users/show.html.erb

<div class="contents row">
  <p><%= @nickname %>さんの投稿一覧</p>
  <% @tweets.each do |tweet| %>
    <%= render partial: "tweets/tweet", locals: { tweet: tweet } %>
  <% end %>
  <%= paginate(@tweets) %>
</div>

※違うフォルダ内の部分テンプレートを呼び出すときは tweets/tweetのようにどのフォルダの部分テンプレートを使用しているかを明示的に記載する。

その後サーバーを立ち上げた状態でマイページにアクセスして、これまでと同様にツイートの一覧が表示されたら成功である。
このように部分テンプレートを使うと同じHTML構造を使い回すことが出来る。

以上で、Ruby on Rails 1章のカリキュラムは全て終了である。
これでRuby on Railsの基礎知識の学習は終わりとなる。
ここまでのレッスンを通して学んだ中で、まだ完全に理解ができていないところもある。 最初の1回目はそれが普通だという。
この状況から脱するためには、薄塗りでも良いのでひたすら量をこなすことが有効であるとのこと。

そのため、ここまでで理解が不足していると思う方や応用カリキュラムに進み理解が追いつかないと感じてきた方は、もう一度PicTweetの作成を繰り返してみよう。
何回も復習することで、プログラミングに対する理解はさらに深まる。

要点チェック