🎀
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