Loading

BLOG

RailsのPresenter パターンについて調べてみた

「クラスを切って、何らかの処理をMVCに当てはまらない場所でさせる」
という方法を勉強したのでまとめておきます。

<% if user.sex == 'male' %>
  <%= link_to "Men's Suites", mens_suits_path %>
<% else %>
  <%= link_to "Women's Bags", womens_bags_path %>
<% end %>


というパターンをViewに書くのはよくあります。
分岐が少ないうちは良いですが、機能追加などで分岐が膨れ上がっていくことも考えられます。
なんとか減らせないものでしょうか?
こういうロジックを書く別の場所として、Presenter(Decoraterともいうそうです)を使います。

Presenterの実装方法も様々あるようですが、PORO(Plain Old Ruby Object)を使うパターンを紹介します。
いろいろ調べてみましたが、この方法が一番シンプルで扱いやすく感じました。

PORO

まずはクラスを切って。

class IndexPresenter
  attr_reader :user
  def initialize(user)
    @user = user
  end

  def link(view)
    if user.sex == 'male'
      view.link_to("Men's Suites", mens_suites_path)
    else
      view.link_to("Lady's Bags", ladys_bags_path)
    end
  end
end

このファイルを別ディレクトリ(例えばapp/presenters)に置きます。
続いて、コントローラーで

class TopController
  def index
    if current_user
      @user = IndexPresenter.new(current_user)
      render action: 'dashboard'
    else
      render action: 'index'
    end
  end
end


としてやります。
そうするとviewが

<%= @user.link(self) %>


とするだけで良くなります。
注意すべきはselfを引数で渡してあげることでしょう。
こうしないとPresenterでlink_toなどView側のメソッドが使えません。

Gemを使う

Presenterもふくめて、Concern, Decorator, Controllerの分割、Service Objectなどたくさんのパターンが実例と一緒にのっているところがありました。

ここを参考にしながら
Draperを使う方法を簡単に紹介します。

さきほどのレポジトリのここによると

 class MicropostDecorator < Draper::Decorator
   def posted_ago
     h.content_tag :span, class: 'timestamp' do
       "Posted #{h.time_ago_in_words(object.created_at)} ago."
     end
   end
 end


というクラスを定義してやると、

<span class="timestamp">		
  Posted <%= time_ago_in_words(feed_item.created_at) %> ago.		
</span>

というHTMLが

  <%= micropost.decorate.posted_ago %>


だけですむようになるようです。使いこなせばPOROと比べて高機能で便利そうに見えます。

しかし、Gem側の挙動がつかみにくく、実装したのを後悔した。という意見もあります。主にMVCの切り分けが曖昧になる、というのが原因のようです

VとCの間でHTMLを生成してしまうと、フロントエンドエンジニアの作業の妨げにならないか心配です。また、たいていのGemでそうですが、シンタックスを覚えないといけない、というのも面倒なところです。Presenterは簡単な分岐処理や、複雑でないHTML要素―例えばリンクやテキストなど―を返す程度にとどめておいたほうが良いように思いました。

その他のパターン

MVCのMとV、VとCを仲立ちするリファクターのパターンはこれだけではありません。

前述のレポジトリにはPresenterもふくめて、Concern, Decorator, Controllerの分割、Service Objectなどたくさんのパターンが実例と一緒にのっています。

「ハートルのRailsチュートリアルをリファクタリングする」というコンセプトのため、
チュートリアルをやったことがある人にはとても参考になると思います。

準備は一歩ずつ

ゴールデンウィーク休業のお知らせ

関連記事

  1. とうとう始まりました!

    2016.08.08
  2. 売却コンサルタントとして感じること

    2016.02.11
  3. マーケティング担当者/企画担当者のデータ活用について

    2016.08.24
  4. 宅地建物取引業者免許証を取得しました

    2015.06.03
  5. 上半期お疲れさまでした!

    2018.10.12
  6. 新しい決済の在り方(カフェで決済)

    2015.05.22
PAGE TOP