Upload
masato-mori
View
1.490
Download
0
Embed Size (px)
DESCRIPTION
一部有志で行ったCrafting Rails4 Applicationsの読み回資料です
Citation preview
Crafting Rails4 Applications
1. Creating Our Own Renderer
Renderer
• render() メソッドによりクライアントに返す形式を柔軟に変更することができる
Post.all の結果を JSON に変換して返す
app/views/shared/not_authenticated で始まる所定のファイル内容を返し, HTTP レスポンスコード 401 を返す
Creating Rails Plugins
rails plugin new pdf_renderer
• Rails plugin の generator
Tree で出したディレクトリツリー
ライブラリ本体
テスト用ディレクトリ
test ディレクトリ以下の構造
dummy 以下にあるのはどうみても Rails アプリそのものです.本当にありがとうございました
${PLUGIN_NAME}.gemspec
• Gem のサマリ情報を書く
Rake tasks
• Plugin 用の Rake タスクがちょいちょい– Rake release で Rubygems に push できるらしい– test の実行は rake test
Dummy application
• 基本的に普通の Rails プロジェクトと同じ– アプリケーション名は dummy
• rails new dummy でできるファイル群とほぼ同じ– 一応 diff してみたけれども,確かにほとんど同じ
PDF 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 )も用意されていた
PDF Renderer 作ろうぜ• こういうのを作りたい
• renderer を拡張すれば, Rails の流儀に従っていい感じに PDF 出力できるじゃん!!
Plugin に gem の dependency 追加
• Plugin で gem を使う場合, Gemfile ではなく gemspec に書く– 書いた後は普通に bundle すれば depend した gem が入る
pdf_renderer.gemspec
• この辺の定義は Gemfile にあったGemfile
この記述で gemspec の dependency を読み込んでいるみたい
とりま Prawn
irb/pry でかきましょー
振る舞いとテストまで書いてみる
動作確認・開発の方法• test/dummy に cd すれば,普通に rails s で
きる– 普通の Rails アプリと同様に開発できるよーlib/pdf_renderer.rb
この記述で :pdf を render() が解釈できるようになる
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
スマホ向けの出し分けなんかで触ったことある人もいるのでは?
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 のインスタンス
_render_template 周り• lookup_context が format 情報を保持しているっぽい
– どのテンプレートが呼び出されるのかの選択に使われる
view_renderer
view_context
Controller -> View への値渡しについて
• Rails 2.3 系まで– View が Controller のインスタンス変数を取りに行っ
ていた• Rails 3.0 から– Controller から View に渡すインスタンス変数を明示
的に指定できるようになった
こうすると View にインスタンス変数が渡らなくなる
拡張するぜ
AbstractController::Layouts
• Rendering の _normalize_options を override した
・・・
もっと拡張
ActionController::Rendering
• DoubleRenderError のチェックとか , status/content_type/location option の処理
ActionController::Renderers
• 特定の symbol 渡しで特殊処理させるためのひな形達
ActionController::Instrumentation
• 処理時間の計測
ActionController::Streaming
• HTTP/1.1 Chunked を使った Rails の Streaming API
render と render_to_string• 違いは見ればわかるよね?
– pdf_renderer みたいに render した中身を string 取得したい時には便利– render_to_string は, DoubleRenderError は発生しない
( ActionController::Rendering#render に実装されているため)– 同じ理由で render_to_string は ctionController::Instrumentation によってベ
ンチマークされない
話を戻すと
• render_to_string({})– _normalize_options() で options = template:
”#{controller_name}/#{action_name}” を生成している
何もしなくても :template option は使える
pdf_renderer.rb
おまけ: ActionController::Base
ApplicationController < ActionController::Base で読み込まれる module 群
まとめ• PDF フォーマットのファイルを返す
pdf_renderer を作る中で, Rails のrendering stack を追ってみたよ
• Rendering stack はモジュール化されているので, render や _normalize_options などのエントリポイントで任意の処理を追加することができるぞ