ruby - Sinatra Request Object -
i'm missing painfully obvious here, can't seem find answer, or work out myself. in sinatra, have self.get
method, captures blocks, when block called, you're able use request
variable inside, how possible?
sinatra
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
app
class app < sinatra::base '/' puts request end end
wow. piqued curiousity, , sure enough, researching facinating. magic starts in compile!
method defined at: 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
notice turn block passed get
(or route function) unbound method via generate_method (defined few lines above). store proc takes 2 parameters, object bind method to, , list of arguments, method called with.
skip ahead 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? , 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) 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
theres lot going on here, key is:
block[self, values]
this calls stored block above self, , appropriate arguments. unbound method bound whatever process_route
bound to( current self
in process_route
). , process_route
bound to? instance of sinatra::base
, know has attribute accessor request
can reached in original block. tada!
Comments
Post a Comment