はじめに
Rails にはデコレータを作るための代表的な Gem として Draper や ActiveDecorator があります。これらの Gem は Rails のモデルオブジェクトを View に特化したオブジェクトにデコレートすることを目的としています。これらは便利ですが、Rails の View 以外、あるいは Rails 以外で使うには、より汎用的な仕組みがほしいです。
実は Ruby の標準ライブラリにそのような仕組みが存在します。それが SimpleDelegator です。今回はこの SimpleDelegator を使ってデコレータを作ってみます。
例
SimpleDelegator を使ってデコレータクラスを作る方法は、SimpleDelegator を継承したクラスを用意するだけです。
class GirlDecorator < SimpleDelegator
def full_name
"#{last_name} #{first_name}"
end
end
class Girl
attr_reader :last_name, :first_name
def initialize(last_name, first_name)
@last_name = last_name
@first_name = first_name
end
end
girl = Girl.new('中川', '夏紀')
decorated_girl = GirlDecorator.new(girl)
decorated_girl.full_name #=> "中川 夏紀"
おまけ
次のようなモジュールを定義すると便利かもしれません (クラス間の結合度は上がりますが) 。
# クラス名 + Decorator という名前のデコレータクラスを定義していることが前提。
module Decoratable
# Draper の API を真似て
# デコレートされたオブジェクトを返すインスタンスメソッドを定義する。
def decorate
# Active Support を使っている場合は
# Object.const_get の代わりに "#{self.class}Decorator".constantize で OK。
decorator_class = Object.const_get("#{self.class}Decorator")
decorator_class.new(self)
end
end
class Girl
include Decoratable
attr_reader :last_name, :first_name
def initialize(last_name, first_name)
@last_name = last_name
@first_name = first_name
end
end
girl = Girl.new('中川', '夏紀')
decorated_girl = girl.decorate
decorated_girl.full_name #=> "中川 夏紀"