RailsでGemを使わずにDecoratorを導入する

2025/11/27

RailsでGemを使わずにDecoratorを導入する方法です。

Class#inheritedを使う

コードから説明するとApplicationRecordに202511272207次のコードを実装します。

app/models/application_record.rb

class ApplicationRecord < ActiveRecord::Base
primary_abstract_class
def self.inherited(subclass)
super
subclass.include "#{subclass.name}Decorator".constantize if Object.const_defined?("#{subclass.name}Decorator")
end
end

https://docs.ruby-lang.org/ja/latest/method/Class/i/inherited.html

RubyのClass#inheritedを使って、ApplicationRecordが継承されたとき、つまりサブクラスとなるモデルクラスが定義されたときにDecoratorをincludeするようにします。

ここではRailsの設計思想であるCoC(設定より規約)を用いて、モデル名に対応するDecoratorを自動でincludeするようにしています。

例えばUserモデルの場合はUserDecoratorを定義しておけば、自動でincludeしてくれます。 わざわざUserモデルにinclude UserDecoratorとする必要はありません。

if Object.const_defined?としているので、モデル名に対応するDecoratorが定義されている場合のみinludeしているので、すべてのモデルのDecoratorを作成する必要はありません。必要なDecoratorだけ定義すればOKです。

Decoratorを定義する

ApplicationRecordで自動でDecoratorをincludeする仕組みを作ったらDecoratorを定義しましょう。

注意するのはDecoratorのmodule名です。 モデル名Decoratorの規約で命名します。

つまりUserモデルであればUserDecorator,PostモデルであればPostDecoratorとします。

Userモデルでfirst_nameとlast_nameカラムをもち、full_nameメソッドをもつDecoratorの定義例です。

app/decoratorsディレクトリを作成して、app/decorators/user_decorator.rbを定義します。

module UserDecorator
def full_name
"#{last_name} #{first_name}"
end
end

規約に沿ったDecorator moduleを作るだけで、自動でincludeされます。

使ってみる

Decoratorを作成したら、試しに使ってみましょう。 ターミナルでRails consoleを立ち上げます。

rails c
> user = User.new(first_name: "tomoya", last_name: "yoshida")
> user.full_name #=> yoshida tomoya

full_nameがかえってきましたね。

注意点

Gemを使わないお手軽Decoratorを実装してみました。 ただしお手軽な分、注意点があります。

ActiveDecoratorなどのGemはViewでしか使えないようになっていますが、今回の実装の場合、View以外でも利用可能です。 つまりどこでも呼び出せてしまうので、本来のDecoratorの使い方をしているかどうかは利用者側に委ねられています。 私はGemを入れると更新コストがかかるので、あまりいれないようにしています。 Gemをいれるか、お手軽実装にするかはプロジェクトに合わせて判断しましょう。