酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

Cells4 - Ruby/Rails でView Components を実現する[Rails4.2]

Railsの部分テンプレートに付随するロジックをコントローラから分離するためのView Componentsを実現する『apotonick/cells - GitHub』の紹介です。


Gemのインストール

Gemfileに以下を追加して、コンソールでbundleを実行してください。

1
2
3
# 部分テンプレートのロジック分離
gem 'cells', "~> 4.0.0"
gem "cells-slim" # cells-erb, cells-haml

Cellsのファイルの生成

comment に対する

1
2
3
4
5
6
7
8
# book の scaffold
rails g scaffold book title:string author:string price:integer
  (省略)

# book の show スタイルを作成
rails g cell book show
      create  app/cells/book_cell.rb
      create  app/cells/book/show.slim

Cellsのrenderについて

部分テンプレートとして表示させたい箇所に以下を記述します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# app/views/books/index.html.slim
table
  thead
    tr
      th title
      th author
      th price
      th action
  tbody
    -# 今回はここで @books をまとめて渡しています
    -# パラメータとかも渡せます。cell style を指定する事もできます(省略するとshow)
    = cell('book', collection: @books)
    # => - @books.each do |book|
    # =>   = cell('book', book) と同義です

これで book_cell.rb に対して @books を一括で渡しています。

Cell::ViewModel について

続いて 先ほど渡された @books の中の book を受け取って処理する部分です。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# app/cells/book_cell.rb
class BookCell < Cell::ViewModel
  include Cell::Slim # erb /haml に変更可能

  # キャッシュする時間を設定できます
  cache :show, expires_in: 10.minutes

  # 呼び出しできるフィールドを指定
  property :title, :author, :price

  def show
    render
  end
end

イメージ的には active_decorator のようなプレゼンテーション層に近いイメージです。

CellのView

1
2
3
4
5
6
7
8
9
10
11
# app/cells/book/show.slim
tr
  td = title
  td = author
  td = price
  td
    = link_to 'Show', model
    = ' / '
    = link_to 'Edit', edit_book_path(model)
    = ' / '
    = link_to 'Destroy', model, data: {:confirm => 'Are you sure?'}, :method => :delete

こんな感じで表示できました。

スクリーンショット 2016-01-13 0.06.56

設計思想を完全には把握できていないですが、以下の説明がしっくりきました。

- ViewModelは、UI要素と結合しないプレゼンテーション・ロジックを担当
- Viewは、UI要素に結合したプレゼンテーション・ロジックを担当

Helperメソッドを使いたい場合

Helperメソッドを使いたい場合は、コントローラ的メソッドの部分に以下を記述。

1
2
3
4
5
6
7
8
# app/cells/book_cell.rb
class BookCell < Cell::ViewModel
  include ActionView::Helpers::UrlHelper
  include ActionView::Helpers::CaptureHelper

  def author_link
    content_tag :div, link_to(model.author, model.author_url)
  end

適切に使いこなせれば、UI Component単位で処理を切り分けられそうです!

公式サイト

CellsのGitHubはこちら。英語ですがわかりやすいのでオススメです。

apotonick/cells · GitHub

Trailblazer framework

Cellsは、Trailblazer frameworkのコンポーネントの一つとしても使われています。

Trailblazerは、チームの学習コストや今後のRailsの進化の方向性によっても導入すべきかは悩ましい…

おすすめの書籍