【问题标题】:How does Sinatra define and invoke the get method?Sinatra 如何定义和调用 get 方法?
【发布时间】:2011-07-08 12:01:54
【问题描述】:

我很好奇这东西是如何工作的。

在需要'sinatra'之后

然后我可以在顶级范围内调用 get()。

深入源码后,发现了这个get()结构

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

知道类

但我唯一想不通的是它在模块 Sinstra 中,如何在不使用 Sinatra:: 解析操作或其他东西的情况下调用 get()?

【问题讨论】:

    标签: ruby metaprogramming sinatra


    【解决方案1】:

    它分散在几个地方,但如果你查看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
    

    由于之前设置的委托,Sinatra 最终将在 Sinatra::Base 上调用 get 方法。

    【讨论】:

    • 由于我目前的水平,这对我来说有点不知所措,我应该了解更多关于元编程的知识,然后再回来阅读你的答案,无论如何谢谢!
    • 确实有点紧张。 Delegator 模块定义了一个委托方法,它基本上只是将对 get 方法的调用重新路由到 Sinatra::Base。当你需要“sinatra”时,这个模块就会被包含进来,所以你可以调用 get,它会去 Sinatra::Base 调用方法。
    【解决方案2】:

    我没有看过 Sinatra 的来源,但它的要点应该是这样的

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

    【讨论】:

    • 感谢您的快速依赖,我只是grep了源代码,里面没有extend self
    • 还有其他方法可以通过模块添加类方法,extend self 只是其中之一。另一种常见的方法是嵌套一个名为ClassMethods 的模块或其他东西,然后使用self.included 挂钩到extend 包含类。结果是一样的,所以我的回答的要点仍然成立。
    • 以“我没有查看源代码,但是”开头的答案并不是对“软件 X 如何实现 Y?”形式的问题的真正答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多