👆
Sinatraでtiltを使う場合には .render(self) する
困ったこと
tilt-jbuilderを使ってSinatraからjbuilderを呼び出そうとしたときのこと。
class Application < Sinatra::Base
get '/ping' do
template = Tilt::JbuilderTemplate.new("views/ping.json.jbuilder")
template.render
end
end
json.code params['code']
bundle exec rackup -p 3000
でサーバーを起動して curl http://localhost:3000/ping?code=123
としても、paramsが未定義のエラーになる。
どうしてparamsが使えないのか。erbだとどうか?
-
erb :'ping'
→ parmasは使えた -
Tilt::ERBTemplate.new('views/ping.erb').render
→ paramsは使えなかった。
Tiltのテンプレートを直列使ってrenderするとparamsが使えないということは、Sinatraが内部でゴニョゴニョしてparamsを使えるようにしていることになる。
erbメソッドはrenderメソッドにそのままスルーパスしてるだけ。
def erb(template, options = {}, locals = {}, &block)
render(:erb, template, options, locals, &block)
end
renderメソッドは、Templateクラスを見つけてrenderしているだけ
template = compile_template(engine, data, options, views)
output = template.render(scope, locals, &block)
このscopeとlocalsが何かというと・・・
locals = options.delete(:locals) || locals || {}
scope = options.delete(:scope) || self
localsは特になにも指定がなく空配列だが、scopeに self
(SinatraのApplicationクラス)が渡されている。
つまり...
これでいい
get '/ping' do
template = Tilt::JbuilderTemplate.new("views/ping.json.jbuilder")
template.render(self)
end
% curl http://localhost:3000/ping?code=123
{"code":123}
Discussion