Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Sinatra define and invoke the get method?

I'm pretty curious about how this thing works.

after require 'sinatra'

then I can invoke get() in the top level scope.

after digging into the source code, I found this get() structure

module Sinatra
 class << self
   def get
    ...
    end
  end
end

know the class << self is open up the self object's singleton class definition and add get() inside, so it starts to make sense.

But the only thing left I can't figure out is it's within module Sinstra, how could get() be invoked without using Sinatra:: resolution operation or something?

like image 344
mko Avatar asked Jul 08 '11 12:07

mko


1 Answers

It is spread out in a few places, but if you look in lib/sinatra/main.rb, you can see this line at the bottom: include Sinatra::Delegator

If we go into lib/sinatra/base.rb we see this chunk of code around like 1470.

  # Sinatra delegation mixin. Mixing this module into an object causes all
  # methods to be delegated to the Sinatra::Application class. Used primarily
  # at the top-level.
  module Delegator #:nodoc:
    def self.delegate(*methods)
      methods.each do |method_name|
        define_method(method_name) do |*args, &block|
          return super(*args, &block) if respond_to? method_name
          Delegator.target.send(method_name, *args, &block)
        end
        private method_name
      end
    end

    delegate :get, :patch, :put, :post, :delete, :head, :options, :template, :layout,
             :before, :after, :error, :not_found, :configure, :set, :mime_type,
             :enable, :disable, :use, :development?, :test?, :production?,
             :helpers, :settings
    class << self
      attr_accessor :target
    end

    self.target = Application
  end

This code does what the comment says: if it is included, it delegates all calls to the list of delegated methods to Sinatra::Application class, which is a subclass of Sinatra::Base, which is where the get method is defined. When you write something like this:

require "sinatra"

get "foo" do
  "Hello World"
end

Sinatra will end up calling the get method on Sinatra::Base due to the delegation it set up earlier.

like image 85
jergason Avatar answered Sep 28 '22 03:09

jergason