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

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -