sinatra响应块中可用的方法
来自1.4.7
halt
使流程直接跳回到invoke。
使用时可带[status code、header、字符串]任意部分或全部,看invoke的逻辑,会被设置到response对象中。
如果什么都不带,则响应会是200,而内容为空。因为Rack::Response初始化时默认status为200,而不带参数的halt又令Base#invoke和Base#call!不去修改response的body
def halt(*response)
response = response.first if response.length == 1
throw :halt, response
end
def invoke
res = catch(:halt) { yield }
res = [res] if Fixnum === res or String === res
if Array === res and Fixnum === res.first
res = res.dup
status(res.shift)
body(res.pop)
headers(*res)
elsif res.respond_to? :each
body res
end
nil # avoid double setting the same response tuple twice
end
pass
使流程直接跳到process_route的末尾,继而进入routes.each的下一循环。
(如果你真的想交由下一个match的路由来处理的话)
def pass(&block)
throw :pass, block
end
def process_route(pattern, keys, conditions, block = nil, values = [])
route = @request.path_info
route = '/' if route.empty? and not settings.empty_path_info?
return unless match = pattern.match(route)
values += match.captures.map! { |v| force_encoding URI_INSTANCE.unescape(v) if v }
if values.any?
original, @params = params, params.merge('splat' => [], 'captures' => values)
keys.zip(values) { |k,v| Array === @params[k] ? @params[k] << v : @params[k] = v if v }
end
catch(:pass) do
conditions.each { |c| throw :pass if c.bind(self).call == false }
block ? block[self, values] : yield(self, values)
end
ensure
@params = original if original
end
redirect
根据http版本设status code,并设置header的Location,然后halt,跳回invoke。
可带参数301(永久移动,迫使browser更新bookmark),这样回到invoke时,会以301替换掉302或303
def redirect(uri, *args)
if env['HTTP_VERSION'] == 'HTTP/1.1' and env["REQUEST_METHOD"] != 'GET'
status 303
else
status 302
end
# According to RFC 2616 section 14.30, "the field value consists of a
# single absolute URI"
response['Location'] = uri(uri.to_s, settings.absolute_redirects?, settings.prefixed_redirects?)
halt(*args)
end
erb等各种template
来自module Template。大概就是使用Tilt来加载具体的模板技术,然后以指定的scope或self来render。无指定scope的话,通过在响应块中设置application的实例变量来让模板引用到
def erb(template, options = {}, locals = {}, &block)
render(:erb, template, options, locals, &block)
end
def render(engine, data, options = {}, locals = {}, &block)
# ...
scope = options.delete(:scope) || self
# ...
begin
layout_was = @default_layout
@default_layout = false
template = compile_template(engine, data, options, views)
output = template.render(scope, locals, &block)
ensure
@default_layout = layout_was
end
# render layout if layout ...
output
end
def compile_template(engine, data, options, views)
eat_errors = options.delete :eat_errors
template_cache.fetch engine, data, options, views do
template = Tilt[engine]
raise "Template engine not found: #{engine}" if template.nil?
case data
when Symbol
# ...
when Proc, String
# ...
else
raise ArgumentError, "Sorry, don't know how to render #{data.inspect}."
end
end
end