Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

32
Crafting Rails4 Applications 1. Creating Our Own Renderer

description

一部有志で行ったCrafting Rails4 Applicationsの読み回資料です

Transcript of Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Page 1: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Crafting Rails4 Applications

1. Creating Our Own Renderer

Page 2: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Renderer

• render() メソッドによりクライアントに返す形式を柔軟に変更することができる

Post.all の結果を JSON に変換して返す

app/views/shared/not_authenticated で始まる所定のファイル内容を返し, HTTP レスポンスコード 401 を返す

Page 3: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Creating Rails Plugins

Page 4: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

rails plugin new pdf_renderer

• Rails plugin の generator

Tree で出したディレクトリツリー

ライブラリ本体

テスト用ディレクトリ

Page 5: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

test ディレクトリ以下の構造

dummy 以下にあるのはどうみても Rails アプリそのものです.本当にありがとうございました

Page 6: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

${PLUGIN_NAME}.gemspec

• Gem のサマリ情報を書く

Page 7: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Rake tasks

• Plugin 用の Rake タスクがちょいちょい– Rake release で Rubygems に push できるらしい– test の実行は rake test

Page 8: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Dummy application

• 基本的に普通の Rails プロジェクトと同じ– アプリケーション名は dummy

• rails new dummy でできるファイル群とほぼ同じ– 一応 diff してみたけれども,確かにほとんど同じ

Page 9: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

PDF Renderer を作る

Page 10: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

actionpack/lib/action_controller/metal/renderers.rb

• とりあえず眺めてみると,– ActionController::Renderers::_renderers に Set が入っている– _renderers は ActionController::Renderers::add() で追加できる

• add(key, &block) の中では _render_option_#{key} を define_method しているだけ

– デフォルトで :json, :js, :xml が定義されている• 何気に JSONP のオプション( callback: true )も用意されていた

Page 11: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

PDF Renderer 作ろうぜ• こういうのを作りたい

• renderer を拡張すれば, Rails の流儀に従っていい感じに PDF 出力できるじゃん!!

Page 12: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Plugin に gem の dependency 追加

• Plugin で gem を使う場合, Gemfile ではなく gemspec に書く– 書いた後は普通に bundle すれば depend した gem が入る

pdf_renderer.gemspec

• この辺の定義は Gemfile にあったGemfile

この記述で gemspec の dependency を読み込んでいるみたい

Page 13: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

とりま Prawn

irb/pry でかきましょー

Page 14: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

振る舞いとテストまで書いてみる

Page 15: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

動作確認・開発の方法• test/dummy に cd すれば,普通に rails s で

きる– 普通の Rails アプリと同様に開発できるよーlib/pdf_renderer.rb

この記述で :pdf を render() が解釈できるようになる

Page 16: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

MIME type の設定• テストを見ると, content-type: application/pdf が勝手に付与され

ているが,これはたまたま PDF の設定がデフォルトであったからActionpack/lib/action_dispatch/http/mime_types.rb

• もしここに設定されていない content-type を指定したい場合, config/initializers/mime_types.rb に書けば良い

Rails new デフォルトの config/initializers/mime_types.rb

スマホ向けの出し分けなんかで触ったことある人もいるのでは?

Page 17: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Renderer を潜る

Page 18: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Render() の流れ

引数を展開して正規化された options hash を作るRender の option が色々な形式に対応しているのはこの辺がやってるrender(:new) とか, render(partial: true) みたいなものを受けて,正しいAction_name に変換したりする

HTTP body に関係の無い部分を options に沿って処理する.status: 401 とかそういうの

view_renderer.render(view_context, options) を呼び出すview_context は ActionView::Base のインスタンス

Page 19: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

_render_template 周り• lookup_context が format 情報を保持しているっぽい

– どのテンプレートが呼び出されるのかの選択に使われる

view_renderer

view_context

Page 20: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

Controller -> View への値渡しについて

• Rails 2.3 系まで– View が Controller のインスタンス変数を取りに行っ

ていた• Rails 3.0 から– Controller から View に渡すインスタンス変数を明示

的に指定できるようになった

こうすると View にインスタンス変数が渡らなくなる

Page 21: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

拡張するぜ

Page 22: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

AbstractController::Layouts

• Rendering の _normalize_options を override した

・・・

Page 23: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

もっと拡張

Page 24: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

ActionController::Rendering

• DoubleRenderError のチェックとか , status/content_type/location option の処理

Page 25: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

ActionController::Renderers

• 特定の symbol 渡しで特殊処理させるためのひな形達

Page 26: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

ActionController::Instrumentation

• 処理時間の計測

Page 27: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

ActionController::Streaming

• HTTP/1.1 Chunked を使った Rails の Streaming API

Page 28: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

render と render_to_string• 違いは見ればわかるよね?

– pdf_renderer みたいに render した中身を string 取得したい時には便利– render_to_string は, DoubleRenderError は発生しない

( ActionController::Rendering#render に実装されているため)– 同じ理由で render_to_string は ctionController::Instrumentation によってベ

ンチマークされない

Page 29: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

話を戻すと

• render_to_string({})– _normalize_options() で options = template:

”#{controller_name}/#{action_name}” を生成している

Page 30: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

何もしなくても :template option は使える

pdf_renderer.rb

Page 31: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

おまけ: ActionController::Base

ApplicationController < ActionController::Base で読み込まれる module 群

Page 32: Crafting Rails4 Applications読み回 1. Creating Our Own Renderer

まとめ• PDF フォーマットのファイルを返す

pdf_renderer を作る中で, Rails のrendering stack を追ってみたよ

• Rendering stack はモジュール化されているので, render や _normalize_options などのエントリポイントで任意の処理を追加することができるぞ