at posts/single.html

Rails に(再)挑戦 7日目 - 一覧表示で本文の一部だけ表示 (Read More)

2日目に一覧表示 (list) と個別表示 (show) でデザインを共有したけど、今は一覧表示のときも本文を全て表示するようになってる。 これを、本文の一部だけ表示して、残りは Read More (個別表示へのリンク) とする。

まずはビューから修正する。 一覧表示 (list.rhtml) と検索結果表示 (search.rhtml) から、 _page.rhtml に対してローカル変数 short (値は true) を渡す。 _page.rhtml では、 short が true だった時に本文の一部だけを表示するようにする。

-<%= render(:partial => 'page', :collection => @pages) %>
+<%= render(:partial => 'page', :collection => @pages,
+           :locals => { :short => true }) %>

_page.rhtml では、ヘルパーの parse メソッド (NoteHelper#parse) を呼び出す時に、 short 変数を渡すように修正する。 同時に、第一引数もページ本文の文字列 (page.body.sub) から、ページオブジェクト (page) に変更した。 これは、 Read More で個別表示のリンクを表示するために、ページの id が必要なため。

       updated: <%=h show_time(page.updated_on) %>
     </div>
-    <%= parse(page.body.sub(/^.*\n/, '')) %>
+    <%= parse(page, short) %>
   </div>

ヘルパー (note_helper.rb) では、 short == true の場合に本文の一部だけを表示する。 具体的には、見出しの行(先頭が「!」で始まる行)以降を、 Read More で置き換えている。

  def parse(page, short = false)
    level = 3
    source = page.body.sub(/^.*\n/, '')
    if short
      source.sub!(%r|^!.*|m) do
        href = url_for(:action => 'show', :id => page.id)
        "([[Read More...|#{href}]])"
      end
    end
    html = HikiDoc.new(source, :level => level).to_html

さっきも書いたけど、 Read More は個別表示へのリンクとする。 個別表示のリンクは、 url_for(:action => 'show', :id => page.id) で取得できる。 これを、 HikiDoc スタイルのリンク文字列にしている。 例えば、 id が 1 のページだったら、以下のようになる。

[[Read More...|/note/show/1]]

これを HikiDoc で変換するとこうなる。

<a href="/note/show/1">Read More...</a>

これでリポジトリにコミット。 リビジョン16か。

少し気になるのは、ヘルパーにパース関連のロジックが集中してきたこと。 最初は Page モデルに to_html メソッドを追加しようかと思ったけど、モデルにビューの処理を書くのも変なので、ヘルパーに書いている。 デフォルトではモデルから url_for は呼べないし。

まぁ、とりあえずコントローラやヘルパーに処理を書いて動かしてしまって、後で処理の場所を移してもいいし。 こうやって少しずつ機能を追加していけるのが、 Rails のいい所かも。

関連する日記