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
通常のオブジェクトを渡すのではなく、デコレートしたオブジェクトを渡すみたいです。これは必要になったときに勉強することにします。
最後に
読んでくださったかた、ありがとうございます。
参考文献
この記事が気に入ったらサポートをしてみませんか?