Draperを使ってみる
Draperとは?
Draperはデコレーター(ビューとモデルの中間の処理を引き受ける)で、railsのプレゼンテーション層を担う。 表示に関するロジックをプレゼンテーション層に引き渡すことで、以下のようなことが避けられる。
- モデルに表示ロジックを記述
- ビューファイル内のif文多用
- helperの名前空間の衝突
結果、コードの可読性、保守性を向上することができる。
draperをインストール
gem 'draper', '~> 1.3'
$ bundle install
土台となるアプリケーションを作成
$ rails g scaffold Blog title:string content:text
draperをインストールしているため、decoratorsも作成されます。
$ rails db:migrate
生成されたコード
class BlogDecorator < Draper::Decorator delegate_all # Define presentation-specific methods here. Helpers are accessed through # `helpers` (aka `h`). You can override attributes, for example: # def created_at helpers.content_tag :span, class: 'time' do object.created_at.strftime("%a %m/%d/%y") end end end
delegate_all
とは、decoratorに存在しないメソッドがコールされた場合、モデルの処理が実行される。
controllerにてdecoratorインスタンスを作成する。
オブジェクトをデコレートする(decorator内で利用できるようにする)ためには、以下の方法を利用します。
- 複数のオブジェクトの場合、decorate_collection
- 単体のオブジェクトの場合、decorate
class BlogsController < ApplicationController before_action :set_blog, only: [:show, :edit, :update, :destroy] # GET /blogs # GET /blogs.json def index @blogs = BlogDecorator.decorate_collection(Blog.all) end ... private # Use callbacks to share common setup or constraints between actions. def set_blog @blog = BlogDecorator.decorate(Blog.find(params[:id])) # これでもいける(model名からdecoratorを推察してくれる) # Blog.find(params[:id]).decorate end end
このようにデコレーターインスタンスを生成します。
ビューからdecoratorメソッドを利用する。
app/views/blogs/index.html.erb
を編集。
<p id="notice"><%= notice %></p> <h1>Blogs</h1> <table> <thead> <tr> <th>Title</th> <th>Content</th> <th colspan="3"></th> </tr> </thead> <tbody> <% @blogs.each do |blog| %> <tr> <td><%= blog.title %></td> <td><%= blog.content %></td> <td><%= blog.created_at %></td> <td><%= link_to 'Show', blog %></td> <td><%= link_to 'Edit', edit_blog_path(blog) %></td> <td><%= link_to 'Destroy', blog, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table> <br> <%= link_to 'New Blog', new_blog_path %>
表示を確認する
draperで定義したメソッドcreated_at
がコールされていることが確認できる。
参考
こちらを参考にさせていただきました。
http://ruby-rails.hatenadiary.com/entry/20150415/1429031791