dar*_*ryl 3 ruby methods class sinatra
我可能在这里遗漏了一些非常明显的东西,但我似乎无法找到答案,或者自己解决这个问题.在Sinatra中,他们有一个self.get捕获块的方法,当一个块被调用时,你可以在request里面使用变量,这怎么可能?
module Sinatra
class Base
class Request < Rack::Request
end
attr_accessor :request
def call!(env)
@request = Request.new(env)
end
class << self
def get(path, opts = {}, &block)
...
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
class App < Sinatra::Base
get '/' do
puts request
end
end
Run Code Online (Sandbox Code Playgroud)
哇.你激起了我的好奇心,果然,研究这个很有吸引力.魔术开始于以下compile!定义的方法:https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1529
def compile!(verb, path, block, options = {})
options.each_pair { |option, args| send(option, *args) }
method_name = "#{verb} #{path}"
unbound_method = generate_method(method_name, &block)
pattern, keys = compile path
conditions, @conditions = @conditions, []
wrapper = block.arity != 0 ?
proc { |a,p| unbound_method.bind(a).call(*p) } :
proc { |a,p| unbound_method.bind(a).call }
wrapper.instance_variable_set(:@route_name, method_name)
[ pattern, keys, conditions, wrapper ]
end
Run Code Online (Sandbox Code Playgroud)
请注意,我们get通过generate_method(上面定义了几行)将传递给(或任何路由函数)的块转换为未绑定的方法.然后我们存储一个proc,它接受两个参数,一个绑定方法的对象,以及一个参数列表,调用该方法.
请跳至process_route:https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L971
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.to_a.map { |v| force_encoding URI.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
Run Code Online (Sandbox Code Playgroud)
这里有很多,但关键是:
block[self, values]
Run Code Online (Sandbox Code Playgroud)
这将使用self和相应的参数调用上面的存储块.因此,未绑定的方法绑定到绑定的任何process_route内容(当前self输入process_route).什么是process_route必然的?Sinatra::Base我们知道的一个实例,request现在可以在原始块中访问属性访问器.田田!
| 归档时间: |
|
| 查看次数: |
1580 次 |
| 最近记录: |