enjoy Railsway!! 第7回 Decorator

Railsアプリケーションの規模が大きくなってくると起こりがちな問題の一つとして、「Modelにあらゆるコードが集中してしまい肥大化してしまう」ことがあります。
今回はその対策としてよく用いられるDecoratorについてご紹介します。

※このコラムのプログラム等は以下の環境で動作確認しています
(2023/11/30 最終確認)
 ruby: ruby 3.2.2 [arm64-darwin22]
 rails: rails (7.1.2)
active_decorator 1.4.1

目次

表示のためのロジックをどこに書くか?

View上で「Userモデルのfirst_namelast_nameを結合してフルネームを表示したい」としましょう。

実現するだけであれば、Viewに直接記述できますがこれは本来Viewが持つべき機能ではありません。可読性も悪くなり、テストコードを書こうとしても煩雑になってしまいます。

app/views/users/show.html.erb

<%- # 良くない例 -%>
<%= "#{@user.last_name} #{@user.first_name}" %>

RailsではViewをシンプルに保つために、こういったロジックはHelperに書くことがより良い方法です。

app/helpers/users_helper.rb

module UsersHelper
  def user_full_name(user)
    "#{user.last_name} #{user.first_name}"
  end
end

app/views/users/show.html.erb

<%- # Helperを使用 -%>
<%= user_full_name(@user) %>

ロジックをViewから分離することはできましたが、この場合オブジェクト指向の観点では@user.full_nameのようにインスタンスのメソッドとして参照する方が自然です。
その場合、Userモデルに実装することはできます。

app/models/user.rb

class User
  def full_name
    "#{last_name} #{first_name}"
  end
end

app/views/users/show.html.erb

<%- # Modelのメソッドを使用 -%>
<%= @user.full_name %>

オブジェクト指向の観点では自然な形にはなりましたが、この調子で表示のためのメソッドを追加していくとModelが肥大化、どんどん大きくなってしまいます。
これを解決するための手法が、Decoratorです。

ActiveDecorator

RailsにDecoratorを導入できるGemはいくつかありますが、今回は ActiveDecoratorをご紹介します。
最初のリリースから既に12年以上を経ていますが、現在でもメンテナンスされRails7.1(edge)への対応も明記されていますので安心して使用できます。

使い方

使い方もシンプルです。
Gemfileactive_decoratorを追加してbundleし、命名規則に従ってmoduleを作成しメソッドを実装するだけでViewから参照することができます。

Userモデルの場合、app/decorators/user_decorator.rbファイルに実装します。
generatorコマンドを利用した生成もできます。

bin/rails g decorator user

app/decorators/user.rb

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

app/views/users/show.html.erb

<%- # Decoratorのメソッドを使用(Viewのコードはそのまま、追加対応不要) -%>
<%= @user.full_name %>

使い方(Action View外)

Viewでは自動的にDecoratorが適用された状態になりますが、その他の箇所で適用して利用することもできます。

# user は通常のActiveRecordインスタンス
decorated_user = ActiveDecorator::Decorator.instance.decorate(user)
decorated_user.full_name # 利用可能

まとめ

Modelの肥大化を軽減するためのDecoratorという手法、そしてDecoratorを導入するGemとしてActiveDecoratorをご紹介しました。

Railsでの開発はどうしても特定のModelに実装が集中してしまいがちです。
その軽減のために様々な手段が長らく議論され、各々で開発手法として試されてきた経緯があります。
一方で、そういったものを次々に取り入れていくと本来のRailsアプリケーションの構成を離れ複雑になってしまい、かえって扱いづらい状況になることもあり賛否両論、という側面も存在します。

しかしDecoratorはご紹介した通りシンプルな要素であり、Railsの扱いやすさを損なわないというメリットがあります。
Modelの肥大化が少しでも気になる方は、まずは取り入れてみることをおすすめします。

著者/文責: 泉 隼人
・Rails技術者認定試験運営委員会 テクニカルアドバイザー
・神奈川工科大学 情報工学科 客員研究員
・鹿児島県 喜界島出身。10歳の頃N88-BASICに触り、コンピューティングにのめり込む
・興味の赴くまま様々なプラットフォーム、言語を楽しみつつ10数年来に渡りRuby on Railsでの開発業務に従事する
・Webサイト https://9uelle.jp/

お知らせ

当委員会ではRails試験を全国300か所で一年中実施をしています。興味がある方は以下をご覧の上、是非受験ください。https://railsce.com/exam

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次