見出し画像

decoratorを導入して、viewの記述をすっきりさせ、modelの肥大化を回避する【Day 3/30 2nd】

こんにちは、たわらです。

本記事は、decoratorを実装する方法を整理した記事です。

decorator(デコレーター)はデザインパターンのひとつ

デザインパターンとは、オブジェクト指向言語で開発を行うときに、先達がまとめた「よく出会う問題とそれに対する良い設計」のことです。

で、よく出会う問題として、veiwに書くか、modelに書くか、という問題があります。具体的には、

「viewに表示したいメソッドを追加したけれど、モデルに書くと肥大化してしまう」という声です。

この問題をうまいこと対処するために生まれたのが、decoratorパターンです。

解決方法としては、

model → decorator → view

のようにして、viewを装飾するメソッドを追加するときなどは、decoratorファイルに記述します。モデルをデコるという考えですね。

gem draper を利用してdecorator層を導入する

Railsではデコレーター層(プレゼンテーション層とも)を導入するには、Draper、またはActive_Decoratorを一般的には利用するそう。

まずGemfileに下記のように記述し、保存してから、bundle installをする。

gem 'draper'

そしたら、ターミナルで、

rails generate draper:install

を実行すると、

rails generate decorator ○○(モデル名)

というようなコマンドが使えるようになります。

モデル名_decorator.rbにコードを書く

こんな感じで書きます。

class hogeDecorator < Draper::Decorator
 delegate_all

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

delegate_all というのは、hogeモデルの全部のメソッドを呼び出せるようにするための記述です。既存のメソッドを組み合わせて、新しいことをしたい場合に便利ですね。

なので、新しく作成したfull_nameメソッドで、hogeモデルの last_nameやfirst_nameメソッドを使用することができるのです。

objectメソッドは、デコレートしているモデルを参照するメソッド、と理解しています。エイリアスがmodel なので、こうも書けます。

#{model.last_name}

hogeモデルの last_nameメソッドを利用する、という宣言です。たぶん。

で、その材料にはhogeモデルのインスタンス変数が保持している情報が使われる、ということです。selfのDraperバージョンという理解です。(いまのところ)

viewに書く

例えばこんなふうに。

<%= current_user.decorate.full_name %><

で、直感的に、current_userというメソッドが返すオブジェクトにデコレート層のfull_nameメソッドを実行している、と理解できます。

このとき、current_userが last_name = ブルー、first_name=ハーツ、というデータを保持している場合、viewには、「ブルー ハーツ」と表示されることになります。

なので、デコレーター層のメソッドを使うときには、.decorateが必要なのですね。

controllerからviewにインスタンス変数を渡すときにも使う

まだ使用したことがないが、こんなふうにも使えるそう。

  def index
   @users = UserDecorator.decorate_collection(User.all)
  end

通常のオブジェクトを渡すのではなく、デコレートしたオブジェクトを渡すみたいです。これは必要になったときに勉強することにします。

最後に

読んでくださったかた、ありがとうございます。

参考文献


この記事が気に入ったらサポートをしてみませんか?