Refinery CMS でデフォルトの Page Parts (ページパーツ)を変更する

Written by @dr_taka_n at 2011/02/26 01:20 [, , , ]

コンテンツの内容を編集する画面のデフォルトは、”Body” と “Side Body” の2つの Page Part を持っている。 ここでは、このデフォルトの Page Parts の設定を変更する方法をメモしておく。基本は以下の内容となる。

以下はデフォルトの管理画面で Home のページを編集しているところになり、”Body” の Page Part を開いているところ。

Page Parts Body

以下は “Side Body” の Page Part を開いているところ。

Page Parts SideBody

表示は以下のようになる。

Page Parts View

デフォルトの Page Part が2つなのは一般的に2カラムのページが多いからそうしたようで、3カラムや1カラムなどのレイアウトを使いたい場合には、管理画面の Page Parts のデフォルトの表示を変更することができる。

Page Part を追加する

管理画面の “Setting” メニューから、”Default Page Parts” の編集ボタンをクリックする。

refinery-setting-default-page-parts

編集ボタンをクリックすると設定ダイアログが表示される。

refinery-setting-default-page-parts

YAML のフォーマットで 現在使用している Page Parts の設定が確認できる。

--- 
- Body
- Side Body

“Another Body” という Page Part を追加してみる。

--- 
- Body
- Side Body
- Another Body

設定を保存後、一旦サーバを再起動させ、新規にページを追加してみる。
“Another Body” という Page Part が増えている。

page-parts-added-part

コンテンツを入力して表示させてみると、

page-parts-added-part

新たに追加した Page Part の表示確認を行えた。

何とも賑やかな表示となっているが、これは生成されたページの内容が既存のスタイルシートとあわなくなっているため。

とりあえず暫定対応として、簡単に体裁を整えるのであれば、RAILS_HOME/public/stylesheets/application.css に以下の内容を追記しておく。

RAILS_HOME/public/stylesheets/application.css:

#body_content_left {
    float: left;
    width: 500px;
}

#another_body {
    float: left;
    width: 150px;
}

#body_content_right {
    float: right;
    width: 250px;
}

少しはマシになる。

page-parts-added-part

Page Part 追加の仕組みを少し覗いてみる

Page Part の追加を行っただけで、スタイルシートはともかく、view の部分もキチンと連携された出力になっていた。
これはどのようにやっているのだろう?

Page Part を追加する前のデフォルトのページの HTML タグの構造と属性指定はざっくりと以下のような感じになる。

<body>
  <div id="site_bar">...</div>
  <div id="page_container">
    <header>
    <section id="page">
      <section id="body_content">
       <h1 id="body_content_title">Home</h1>
       <section id="body_content_left"> Part Body のコンテンツ </div>
       <section id="body_content_right"> Part Side Body のコンテンツ </div>
      </section>
    </section>
    <footer>...</footer>
  </div>
</body>

“Another Body” の Page Part の追加をしたことで、「Part Side Body のコンテンツ」の後に、

       <section id="another_body"> Part Another Body のコンテンツ </div>

が追加された。

先ほどの Page Part の追加の作業だけで、

  • section タグの追加
  • その id 属性を Page Part に指定した Another Body の名称から生成
  • “Another Body” の Page Part で記載された内容をそのタグ内に表示

までが行われている。

Page の view は、refinerycms-pages にあるデフォルトのテンプレート /app/views/pages/show.html.erb によってレンダリングされている。

GEM_PATH/gems/refinerycms-pages-0.9.9.3/app/views/pages/show.html.erb:

<%= render :partial => "/shared/content_page" %>

ここでレンダリングされているパーシャルテンプレート /shared/content_page を見てみると理由がわかる。このパーシャルテンプレートは、refinerycms-core にある。ちょっと長いが、そのままソースを引用する。

GEM_PATH/gems/refinerycms-core-0.9.9.3/app/views/shared/_content_page.html.erb:

<%
  # provide a default array for collecting CSS for sections
  css = []

  # if 'sections' is passed in as a local_assigns, all of this is ignored.
  if local_assigns[:sections].blank?
    # always have a title
    sections = [{:yield => :body_content_title, :fallback => page_title, :title => true}]

    # append sections from this page.
    @page.parts.inject(sections) do |s, part|
      # we have some default yields, body_content_left and body_content_right
      # these map to 'body' and 'side_body' fields in default Refinery.
      section = {:fallback => part.body}
      section[:yield] = case (title_symbol = part.title.to_s.gsub(/\ /, '').underscore.to_sym)
        when :body then :body_content_left
        when :side_body then :body_content_right
        else title_symbol
        end

      # add section to the list unless we were specifically requested not to.
      # otherwise, add css saying it's been removed.
      unless (local_assigns[:hide_sections]||=[]).include?(section[:yield])
        s << section
      else
        css << "no_#{section[:yield]}"
      end
    end unless @page.nil? or @page.parts.blank?

    # Ensure that even without @page.parts we still have body_content_left and body_content_right
    all_yields = sections.collect{|s| s[:yield]}
    sections << {:yield => :body_content_left} unless all_yields.include?(:body_content_left)
    sections << {:yield => :body_content_right} unless all_yields.include?(:body_content_right)
  end

  # you can add more sections to the list using something like this:
  # sections |= [{:yield => :something_else, :fallback => another_method, :id => 'something'}]

  sections.each do |section|
    section[:html] = yield(section[:yield]) if section[:yield].present?

    if section[:html].blank? and !local_assigns[:show_empty_sections] and
       !local_assigns[:remove_automatic_sections] and section.keys.include?(:fallback) and
       section[:fallback].present?
      section[:html] = raw(section[:fallback])
    end

    dom_id = section[:id] || section[:yield]
    if section[:html].present?
      if section[:title]
        section[:html] = "<h1 id='#{dom_id}'>#{section[:html]}</h1>"
      else
        section[:html] = "<section id='#{dom_id}'>#{section[:html]}</section>"
      end
    else
      css << "no_#{dom_id}"
    end
  end
-%>
<section id='body_content'<%= " class='#{css.join(' ')}'" if css.present? %>>
  <%= raw sections.map{|section| section[:html]}.join("\n") -%>
</section>
<%= render :partial => '/shared/draft_page_message' unless @page.nil? or @page.live? -%>

ロジック盛りだくさんのパーシャルテンプレートだが、、このパーシャルテンプレートのお陰で、追加された Page Part がキチンとハンドリングされている。

ちなみに、Page の view である /app/views/pages/show.html.erb、また、先ほどの /app/views/shared/_content_page.html.erb のデフォルトの表示を変えたい場合には、Refinery CMS のお作法にそって、自身の Refinery アプリに gem からソースをコピーしておいて編集(Refinery 的にはオーバーライド)する。

$ rake refinery:override view=pages/show
(in /home/hoge/work/try-refinery)
Copied view template file to app/views/pages/show.html.erb

$ rake refinery:override view=shared/_content_page
(in /home/hoge/work/try-refinery)
Copied view template file to app/views/shared/_content_page.html.erb

Rails の普通のテンプレートなので、Rails でのやり方そのままにカスタマイズが行える。

blog comments powered by Disqus