DraperとActiveDecoratorの比較

前置き

シンプルなRailsMVCの3層です.
Fat Modelをさけるために, Decorator層を作成し,
表示に関するロジックをDecorator層に閉じ込めます.
これはシステム規模が大きくなるにつれ, Fat modelを
避けるためによく使われる方法の一つです.

Decorator層を実現するために使われるgemとして

の2つがあります.

結論

Draper

  • decorator以外にもview_objectなども使って, viewロジックを管理する場合.
  • 中規模以上のシステム.

の場合採用

ActiveDecorator

  • viewロジックをdecoratorだけで管理する場合.
  • 小規模システム.

の場合採用

比較

decorator の実装

Draper
class PenDecorator < ApplicationDecorator
  delegate_all

  def created_at
    "Hello at #{object.created_at}"
  end
end

Decoratorクラスを実装する.
オリジナルクラスのインスタンス
objectで取得可能.

ActiveDecorator
module PenDecorator
  def created_at_str
    "Hi! at #{created_at}"
  end
end

moduleを実装する.
元クラスにincludeされてるかのように振る舞うので,
オリジナルのメソッドをそのまま使える.
(ざっくりコード読んだ感じ元クラスにincludeされてはなさげ. 要確認.)
オリジナルと同名メソッドを定義して,
その中でオリジナルのメソッドを呼ぶと無限ループで死ぬ.

decoration方法

Draper
class HogeController
  def show
    @hoge = Hoge.first.decorate
    p @hoge.class #=> HogeDecorator
  end
end

Hogeクラスのインスタンスに対してdecorateメソッドを呼び出す.
decorateメソッドがHogeDecoratorクラスを返すので, Decoratorの
メソッドが使用可能になる.
Decoratorのメソッドを使いたい時にdecorateすればどこでも使える.

ActiveDecorator

以下の状況で自動でDecoratorのメソッドが使えるようになる.

英語原文: https://github.com/amatsuda/active_decorator


なのでcontroller内でデフォルトではDecoratorのメソッドは使えない.
以下のようにdecorate化すると使えるようになる.

class HogeController
  def show
    @hoge = Hoge.first
    ActiveDecorator::Decorator.instance.decorate(@hoge)
    p @hoge.class #=> Hoge
    p @hoge.created_at_str #=> "Hi! at 2018-01-01 00:00:00"
  end
end

メリット, デメリット

Draper

Decoratorのメソッドを使いたい時に, Decoratorクラスのインスタンス
を呼び出してるのがわかりやすい.
変数に入ってるのがDecoratorクラスなのかオリジナルのクラスなのか,
わけわからんくなる. (変数名などに工夫がいる?)
なんとなく大げさな事やってる感ある. (完全主観)

ActiveDecorator

viewロジックをmodule管理してincludeしてる(ような感じ)が好き.
View以外でDecoratorのメソッドを使いたい時のdecoration方法がなんとなく微妙.
そもそもview以外で使うべきじゃないよねって思想のもと設計されてそう.
その設計にしっかり乗れるシステムならこっち.