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?
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.
I haven't looked at the source of Sinatra, but the gist of it should be something like
>> module Test
.. extend self
.. class << self
.. def get; "hi";end
.. end
.. end #=> nil
>> include Test #=> Object
>> get #=> "hi"
精彩评论