Как Синатра определяет и вызывает метод get? - PullRequest
7 голосов
/ 08 июля 2011

Мне довольно любопытно, как эта штука работает.

после 'Синатра'

тогда я могу вызвать get () в области видимости верхнего уровня.

после копания в исходном коде я нашел эту структуру get ()

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

знать, что класс << self открывает определение синглтон-класса объекта self и добавляет внутрь get (), так что это начинает иметь смысл. </p>

Но единственное, что я не могу понять, это то, что он находится внутри модуля Sinstra, как можно вызывать get () без использования операции Sinatra :: resolution или чего-то такого?

Ответы [ 2 ]

10 голосов
/ 08 июля 2011

Это разбросано в нескольких местах, но если вы посмотрите на lib/sinatra/main.rb, вы можете увидеть эту строку внизу: include Sinatra::Delegator

Если мы перейдем к lib/sinatra/base.rb, мы увидим этот кусок кода примерно как 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

Этот код выполняет то, что говорит комментарий: если он включен, он делегирует все вызовы в список делегированных методов классу Sinatra::Application, который является подклассом Sinatra::Base, где находится метод get определены. Когда вы пишете что-то вроде этого:

require "sinatra"

get "foo" do
  "Hello World"
end

Синатра в итоге вызовет метод get на Sinatra::Base из-за делегирования, которое он установил ранее.

0 голосов
/ 08 июля 2011

Я не смотрел на источник Синатры, но суть его должна быть что-то вроде

>> module Test
..   extend self
..   class << self
..     def get; "hi";end
..     end
..   end #=> nil
>> include Test #=> Object
>> get #=> "hi"
...