Post on 15-May-2015
description
デコレータのはなし
渋谷.rb[:20130918]Takeshi Yabe / @tyabe
app/views/posts/show.slim- if @post.image.present? = image_tag @post.image.url- else = image_tag ‘default.png’
こんなのがどんどんどんどん増えてくる
view
models/post.rbclass Post < ActiveRecord::Base def image_url if self.image.present? self.image.url else ‘default.png’ end endend
app/views/posts/show.slim= image_tag @post.image_url
model?
models/post.rbclass Post < ActiveRecord::Base def image_url if self.image.present? self.image.url else ‘default.png’ end endend
app/views/posts/show.slim= image_tag @post.image_url
View用のメソッドがModelに入っている
キモい
model?
Helper?
app/helpers/posts_helper.rbStitchStitch::App.helpers do # ...end
・メソッド名の衝突を気にする必要がある・OOPっぽくない
models/post.rbclass Post < ActiveRecord::Baseend
app/controllers/posts_controller.rbSampleProject::App.controllers :posts do get :show, with: :id do post = Post.find(params[:id]) @post_decorator = PostDecorator.new(post) render ‘posts/show’ endend
app/views/posts/show.slim- if @post_decorator.is_new_page? = image_tag @post_decorator.image
app/decorators/posts_decorator.rbclass PostDecorator attr_reader :post
def initialize(post) @post = post end
def image_url if self.image.present? self.image.url else ‘default.png’ end endend
表示用のロジックを Decorator に移す
spec/app/decorators/post_decorator_spec.rbrequire 'spec_helper'
describe "PostDecorator" do it 'can construct a new instance' do post = create(:post) @post_decorator = PostDecorator.new(post, self) expect(@post_decorator.image_url).to eq ‘default.png’ endend
テストも書きやすくなる
気軽に使いたいのでGeneratorを作った
$ padrino g decoratorUsage: padrino-gen decorator [name]
Options: -r, [--root=ROOT] # The root destination # Default: . -a, [--app=APP] # The application destination path # Default: /app -d, [--destroy] -n, [--namespace=NAMESPACE] # The name space of your padrino project
Description: padrino-gen decorator generates a new Padrino decorator
つかいかた
$ tree .├── app
│ ├── app.rb
│ ├── controllers
│ ├── decorators
│ │ └── post_decorator.rb
│ ├── helpers
│ └── views
└── spec
└── app
└── decorators
└── post_decorator_spec.rb
Decorator用のファイルをつくります
Rails
Draper も実現することは基本的には同じですが、方式に違いがあります。ActiveDecorator はモデルオブジェクトにモジュールを extend するのに対し、Draper はモデルオブジェクトをラップするオブジェクトを作ってメソッドを移譲します。
Draper の方式ではメソッドを追加する前とした後でオブジェクトの identity が変化してしまうため、よくよく注意しないとハマります。
引用:Rubyist Magazine - Ruby on Rails: The Bad Partshttp://magazine.rubyist.net/?0041-RailsTheBadParts
Let's talk about it.