🎀

Decoratorパターンとは(Rails)

に公開

はじめに

Railsで開発を続けていると、次第にモデルやビューが表示ロジックでごちゃごちゃしてきます。
「モデルに書くのも違うし、ビューに書くと読みにくい…」

そんなときに使えるのが Decoratorパターン
DraperというGemを使った実装方法をメインに、補足として Draperなし(プレーンRuby)の手法 も紹介します。


Decoratorパターンとは?

Decoratorパターンは、オブジェクトに表示用の追加ロジックを後から与えるデザインパターンです。
Railsでは「Fat Model」「Fat View」を回避するために活用されることが多いです。

Fat Viewの例

<%= "#{user.first_name} #{user.last_name}".titleize %>
<%= user.updated_at.strftime('%Y年%m月%d日') %>

Fat Modelの例

def full_name
  "#{first_name} #{last_name}".titleize
end

def formatted_updated_at
  updated_at.strftime('%Y年%m月%d日')
end

→ 表示ロジックをモデルにもViewにも書かず、Decoratorに切り出す!


Draperとは?

Draperは、RailsにおけるDecoratorパターンの実装を簡単にするためのGemです。

主に以下の特徴があります:

  • モデルのメソッドを自動的に委譲できる delegate_all
  • モデルに decorate メソッドを追加して、簡単にラップできる
  • View専用のロジックをクラス単位で切り出せる

Railsらしい書き方ができ、再利用やテストもしやすくなるため、中〜大規模のアプリで特に有効です。


Draperを使ったDecoratorの実装手順

1. Gemをインストール

bundle add draper
rails generate decorator User

2. デコレータークラスを定義

# app/decorators/user_decorator.rb

class UserDecorator < Draper::Decorator
  delegate_all  # モデルの全メソッドを自動で委譲

  def full_name
    "#{first_name} #{last_name}".titleize
  end

  def formatted_updated_at
    updated_at.strftime('%Y年%m月%d日')
  end
end

3. コントローラーやViewで使う

# コントローラーでdecorate
@user = User.find(params[:id]).decorate
<!-- View -->
<%= @user.full_name %>
<%= @user.formatted_updated_at %>

Draperのメリット

メリット 説明
✅ delegate_all による自動委譲 モデルのメソッドを再定義せずそのまま使える
✅ シンタックスシュガー .decorate スマートなラッピングが可能
✅ Railsらしい記述スタイル 他プロジェクトでも馴染みやすい

補足:Draperを使わずにDecoratorを作る方法

「Gemを使いたくない」「シンプルな構成にしたい」という場合は、DraperなしでもDecoratorは実装可能です。

1. 自作デコレータークラス

# app/decorators/user_decorator.rb
class UserDecorator
  def initialize(user)
    @user = user
  end

  def full_name
    "#{@user.first_name} #{@user.last_name}".titleize
  end

  def formatted_updated_at
    @user.updated_at.strftime('%Y年%m月%d日')
  end
end

2. 使用方法

@user = User.find(params[:id])
@decorated_user = UserDecorator.new(@user)
<%= @decorated_user.full_name %>
<%= @decorated_user.formatted_updated_at %>

注意点

  • Draperのような delegate_all は自前で実装が必要
  • .decorate という糖衣構文は使えない

とはいえ、軽量で学習コストが低いという利点があります。


まとめ

Decoratorパターンは、表示ロジックをモデルやViewから切り離し、コードをスッキリさせるための強力な武器です。

  • 複雑なビューが増えてきたらDraperの導入を検討
  • 小さな表示整理だけならプレーンRubyでも十分

Discussion