DraperとActiveDecoratorの比較
前置き
シンプルなRailsはMVCの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のメソッドが使えるようになる.
- controllerからviewに, ActiveRecord::Base, ActiveRecord::Relationのinstanceを渡す時
- viewでActiveRecord::Baseのmodel(s)を渡してpartialをrenderするとき
- デコレートされたインスタンスからassociationを取得する時
英語原文: 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以外で使うべきじゃないよねって思想のもと設計されてそう.
その設計にしっかり乗れるシステムならこっち.