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