『Ruby on Rails 5 アプリケーションプログラミング』を学習する12

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

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

序文

Ruby on Rails 5 アプリケーションプログラミング」学習12日目。
本体よりもはてなブログで宣伝したやつのほうがGoogle上位に表示されてしまう悲しみ。

GitHub

github.com

進捗

  • 第4章 ビュー開発
    • 4.6 ビューヘルパーの自作
      (学習時間:3.5時間)

コード実装部分

↓/config/routes.rb

# 省略

  get  'view/helper'
  get  'view/helper2'
  get  'view/helper3'
end

↓/app/helpers/view_helper.rb

module ViewHelper
  # 日付時刻値を整形して表示するヘルパーメソッド
  # datetime : 整形対象の日付時刻値
  # type : 出力形式
  def format_datetime(datetime, type = :datetime)
    # 後置unless(後置if)という記法
    return '' unless datetime

    case type
      when :datetime
        format = '%Y年%m月%d日 %H:%M:%S'
      when :date
        format = '%Y年%m月%d日'
      when :time
        format = '%H:%M:%S'
    end

    datetime.strftime(format)
  end

  # collection : リストのもととなるオブジェクト配列
  # prop : 一覧するプロパティ名
  def list_tag(collection, prop)
    # pp collection.inspect
    # pp 'coll : ' + collection.to_s
    # pp 'prop : ' + prop.to_s
    # content_tag => htmlタグを出力する
    # content_tagのブロックはブロック内の処理結果をcontentとして扱う
    # content_tagメソッドを使うことで適切なエスケープができる
    content_tag(:ul) do
      collection.each do |element|
        # concatメソッドはRubyの結合を行うものではなく、
        # Railsの出力を行うメソッドのようだ!
        concat content_tag(:li, element.attributes[prop])
      end
    end
    # 出力例
    # <ul><li>充分未来</li>
    # <li>星眠る島</li>
    # <li>カンバセイション</li>
    # <li>僕は停滞気味</li>
    # <li>エロス</li>
    # <li>MICHITONOSOGU</li>
    # <li>つしまげる</li>
    # <li>すてきな15才</li>
    # <li>KICK!</li>
    # <li>AOKAJI</li></ul>
  end

  # list_tagメソッドをcontent_tagメソッドを使わずに書き換えた例
  def list_tag2(collection, prop)
    list = '<ul><li>bbb</li>'
    collection.each do |element|
      # これはRubyの結合を行うほうのconcat!
      list.concat('<li>')
      # h はRails側のメソッドでエスケープ処理を行っている
      # 1文字のメソッドとか作るな
      list.concat(h element.attributes[prop])
      list.concat('</li>')
    end
    # 返す値はタグを有効にする必要がある
    raw list.concat('</ul>')
    # エスケープしたり解凍したりややこしいから
    # なるべく頑張ってcontent_tagを使おう!
  end

  # 引用部分をフォーマットする
  def blockquote_tag(cite, citetext, options = {}, &block)
    # mergeメソッドでoptionsのハッシュにciteオプションを追加
    options.merge! cite: cite
    # options => {:class=>"quote", :cite=>"http://www.wings.msn.to"}

    # captureメソッド : 与えられたブロックを解釈し結果を文字列で返す    
    # capture(&block) =>
    # "\n" +
    # "  WINGSプロジェクトは、当初、ライター山田祥寛のサポート(検証・査読・校正作業)集団という位置づけで開始されたコ
    # ミュニティでしたが、2002年12月にメンバを大幅に増強し、本格的な執筆者プロジェクトとして生まれ変わりました。<br />\n" +
    # "  <img src=\"http://www.wings.msn.to/image/wings.jpg\" alt=\"Wings\" />\n"

    quote_tag = content_tag(:blockquote, capture(&block), options)
    # quote_tag =>
    # "<blockquote class=\"quote\" cite=\"http://www.wings.msn.to\">\n" +
    # "  WINGSプロジェクトは、当初、ライター山田祥寛のサポート(検証・査読・校正作業)集団という位置づけで開始されたコ
    # ミュニティでしたが、2002年12月にメンバを大幅に増強し、本格的な執筆者プロジェクトとして生まれ変わりました。<br />\n" +
    # "  <img src=\"http://www.wings.msn.to/image/wings.jpg\" alt=\"Wings\" />\n" +
    # "</blockquote>"

    p_tag = content_tag(:p) do
      concat '出典:'
      concat content_tag(:cite, citetext)
    end
    quote_tag.concat(p_tag)
  end
end

↓/app/views/view/helper.html.erb

<%# ビューヘルパーを使う例(helpers/view_helper.rb参照) %>
<%# ビューヘルパーはhelpers配下に記述する %>

<% current = Time.now %>

<%= format_datetime(current, :datetime) %><br />
<%# 2018年04月04日 04:42:48<br /> %>

<%= format_datetime(current, :date) %><br />
<%# 2018年04月04日<br /> %>

<%= format_datetime(current, :time) %><br />
<%# 04:42:48<br /> %>

↓/app/views/view/helper2.html.erb

<% @cds = Cd.all %>
<%= list_tag2 @cds, 'title' %>
<%# 
    # <ul><li>充分未来</li>
    # <li>星眠る島</li>
    # <li>カンバセイション</li>
    # <li>僕は停滞気味</li>
    # <li>エロス</li>
    # <li>MICHITONOSOGU</li>
    # <li>つしまげる</li>
    # <li>すてきな15才</li>
    # <li>KICK!</li>
    # <li>AOKAJI</li></ul>
 %>

↓/app/views/view/helper3.html.erb

<%= blockquote_tag('http://yjkym.hatenablog.com/', '大塚製薬', class: 'please') do %>
  カロリーメイトは、手軽にバランス良く栄養補給できるバランス栄養食です。<br />
  <%= image_tag('https://www.otsuka.co.jp/cmt/images/mv2.jpg') %>
<% end %>
<%# ↓出力結果
<blockquote class="please" cite="http://yjkym.hatenablog.com/">
  カロリーメイトは、手軽にバランス良く栄養補給できるバランス栄養食です。<br />
  <img src="https://www.otsuka.co.jp/cmt/images/mv2.jpg" alt="Mv2" />
</blockquote><p>出典:<cite>大塚製薬</cite></p> 
%>

実行結果

f:id:yjkym:20180404161949p:plain

感想

1項ぐらいすぐ終えて、あわよくばもう少し頑張ろうかなーと思ってたのに、結局1項だけで時間いっぱいかかってしまった。

難しかった…。
rubyの後置ifとか、content_tag()メソッドの仕様とか謎のhメソッドとか(誤植かと思った)。

一番混乱したのがconcat()メソッド。
正しい理解なのか自信ないけど、concat()メソッドってRubyで定義されているものとRailsで(?)定義されているものと2種類あって、役割が全然違うんですね…。
Rubyのconcat()は配列や文字列を結合するメソッドだけど、Railsで(?)定義されているconcat()メソッドはブロック内で出力を行うだけみたい。(自信ない)

特に説明なく両方が一緒に使われてるからそりゃ混乱するよー。
Railsで定義されてるメソッドだからRubyのリファレンスには当然載ってないから余計パニックに。

こんなことがあるということは、Railsを学習する前にRubyを学習するべきなんだろうけど、Rubyを学習する動機のほとんどはRails目的であろうという…なんていうのこういうの。鶏と卵? メビウスの輪
でもなんとかコードを読み解けたのはよかった。
カロリーメイトください。

BGM

who am I? / せりかな www.youtube.com