いきなり詳しくはこちら
withについて
通常のDecoratorではなく、別のDecoratorを使いたい時に指定する。
例えば、ユーザは個々の詳細画面(プロフィール画面とか)持ってて、管理者側からは別の詳細画面を作る場合。
class UserDecroator < ApplicationDecorator
delegate_all
def show_link(options = nil)
options ||= {}
h.link_to(name, user_path(object), options)
end
end
class Admin::UserDecorator < ApplicationDecorator
delegate_all
def show_link(options = nil)
options ||= {}
h.link_to(name, admin_user_path(object), options)
end
end
@users.decorate.each do |user|
user.show_link
# => <a href="/users/1">ほげ</a>
end
@users.decorate(with: Admin::UserDecorator).each do |user|
user.show_link
# => <a href="/admin/users/1">ほげ</a>
end
contextについて
追加でデータを渡したい場合に使うらしい。
こんなユースケースあるか知らんがこんな感じ。
class UserDecroator < ApplicationDecorator
delegate_all
def show_link(options = {})
options.merge(context[:show_link_options] || {})
h.link_to(name, user_path(object), options)
end
end
class Admin::UserDecorator < ApplicationDecorator
delegate_all
def show_link(options = {})
options.merge(context[:show_link_options] || {})
h.link_to(name, admin_user_path(object), options)
end
end
@users.decorate(context: { show_link_options: { target: '_blank' } }).each do |user|
user.show_link
# => <a target="_blank" href="/users/1">ほげ</a>
end
@users.decorate(with: Admin::UserDecorator, context: { show_link_options: { target: '_blank' } }).each do |user|
user.show_link
# => <a target="_blank" href="/admin/users/1">ほげ</a>
end
何が嬉しいのか
前まで、user.admin_show_linkみたいな感じで書いてたのをdecoratorクラス分けて書くようになって、よりオブジェクト指向っぽくなった。
なぜもっと早く気がつかなかったし。
感想、というか愚痴
これDraper::CollectionDecoratorには使えるけど、ActiveRecordのインスタンスに生えるdecorateメソッドにはcontextしか対応していないのでuser.decorate(with: Admin::UserDecorator)みたいなのできない。Admin::UserDecorator.new(user)って書き方。
欲しいなぁと思いつつdecorator側に無いあたり敢えて外してるんだろうかと勘ぐったり。
あと、decorates_associationで関連モデルもまとめてdecorateできるようになってるけど、これ欲しい場合と欲しく無い場合の切り分けにそれぞれクラス作る必要が出てくる。
この辺ももうちょい柔軟に使えたら便利な気もする(もしくはできない方が良いケースが多い?