進撃のまたぞー

佐賀在住のアラサーです。プログラミング学習で学んだことを発信していきます。

gem Draperを初めて使用したので振り返り

はじめに

今回、初めてDraperを使用したのでまとめとして書いています。

Draperとは?

ざっくりいうとDecoratorを導入するのに便利なgemです。

Decoratorとは?

こちらの記事が凄く分かりやすかったです。

Decorator と Presenter を使い分けて、 Rails を ViewModel ですっきりさせよう - KitchHike Tech Blog

Decoratorの役割とDraperについて - Qiita

DecoratorとはViewModelの一種です!!(記事を参考にしています)
もう少し言いますと単一のモデルクラスに対応するViewModelです。

viewに表示用のロジックを直接書いていった場合に規模が大きくなるにつれて、
重複する部分が発生する可能性があります。
そうなると、保守性が低下してしまうという弊害が発生してしまいます。

これを回避しようすると以下のような事を思いつくと思います。

  • Modelに切り出す
    リファクタリングの一つにControllerは薄く、Modelは厚くという考えがあります。
    しかし、表示用のロジックが多くなるにつれてModelが肥大化し、見通しが悪く
    なります。

  • helperに切り出す
    helperを使用する場合はmodelに関連しない表示ロジックを記載するのがいいです。
    また、helperにはscopeの問題があります。viewでは全てのhelperが参照できる為、
    メソッド名が衝突する可能性があります。
    こちらの記事が分かりやすかったです。

  • ViewModelに切り出す(<= やること!!)
    viewに関するロジックを切り出してViewModelモデルに集約する。

導入方法

こちらを参考にしてください。

rails generate draper:install 
# => decorators/application_decorator.rbを作成します。

Decoratorを作成するには以下を実行します。

$ rails generate decorator User
# Userモデルがあるという前提です!!
# => decorators/user_decorator.rbを作成します。

中身を見ています

decorators/user_decorator.rb

class UserDecorator < Draper::Decorator
  delegate_all

end

delegate_allメソッドはDecorator内にないメソッドが呼び出された場合、
Model(ここではUser)のメソッドを呼び出します。

helperにアクセスする場合

  • hメソッドでアクセスできる。(Rails,自作両方可)
  • helpersでもアクセス可能。
class ArticleDecorator < Draper::Decorator
  def emphatic
    h.content_tag(:strong, "Awesome")
  end
end

Modelにアクセスする場合

class ArticleDecorator < Draper::Decorator
  def published_at
    object.created_at.strftime("%A, %B %e") # <= objectでアクセス可能
    model.created_at.strftime("%A, %B %e") # <= modelはエイリアス
  end
end

delegate_allが宣言されている場合

先程のobjectを省略できます。

class ArticleDecorator < Draper::Decorator
  delegate_all 
  def published_at
    created_at.strftime("%A, %B %e") 
  end
end

オブジェクトをDecorateする方法

  • オーソドックス
    モデル名からDecoratorを推測するので、両方の名前を合わせる必要がある。
@user = User.find(params[:id]).decorate

名前が異なる場合でも以下のようにするとdecorateできる。

@user = ProductDecorator.new(User.first)
@user = ProductDecorator.decorate(User.first)

注:allを使用してオブジェクトを取得する場合、rails3だと配列を返すのでdecorate_collectionを使う。

#rails3まで
@users = UserDecorator.decorate_collection(User.all)

# rails3以降ではdecorateでok
@users = User.all.decorate

他にも様々なメソッドが用意されています!!
是非、参考サイトにアクセスして確認してください!!

参考

GitHub - drapergem/draper: Decorators/View-Models for Rails Applications

Draperの使い方 まとめ - 猫Rails

Decoratorの役割とDraperについて - Qiita