Ruby 使全局方法在类中可访问

Ruby 使全局方法在类中可访问,ruby,sinatra,Ruby,Sinatra,考虑以下sinatra应用程序: require 'sinatra' def f settings.development? ? 'development' : 'whatever' end class C def self.f settings.development? ? 'development' : 'whatever' end end get '/' do # f # works C.f # doesn't work

考虑以下
sinatra
应用程序:

require 'sinatra'

def f
    settings.development? ? 'development' : 'whatever'
end

class C
    def self.f
        settings.development? ? 'development' : 'whatever'
    end
end

get '/' do
    # f   # works
    C.f   # doesn't work, gives "NameError - undefined local variable or method `settings' for C:Class"
end
这里发生了什么?我如何使其工作?

试试:

class C
  def self.f
    Sinatra::Application.settings.development? ? 'development' : 'whatever'
  end
end
当您
需要'sinatra'
时,会发生以下情况:

Sinatra::Delegator
类负责在
main
对象中提供,以及
get
DSL和创建Sinatra应用程序所需的所有功能。

尝试:

class C
  def self.f
    Sinatra::Application.settings.development? ? 'development' : 'whatever'
  end
end
当您
需要'sinatra'
时,会发生以下情况:


Sinatra::Delegator
类负责在
main
对象中提供,以及
get
DSL和创建Sinatra应用程序所需的所有功能。

发生的情况是,在定义新类时,您失去了对外部范围的访问,因为它为您提供了自己的范围

如上所述,要求Sinatra运行
extend Sinatra::Delegator
,它添加了所有已知的方法

考虑到这一过度简化:

module A
  def ping
    "pong"
  end
end

ping # => throws NoMethodError
extend A
ping # => "pong"

class B
  def my_ping
    ping
  end
end

B.new.my_ping # => throws NoMethodError
为什么??因为Ruby的范围规则

您可以通过向外部范围传递引用来解决这个问题

module A
  def ping
    "pong"
  end
end

extend A
ping # => "pong"

class B
  class << self
    attr_accessor :app

    def my_ping
      app.ping
    end
  end
end

B.app = self
B.my_ping # => "pong"
模块A
德平
“乒乓球”
结束
结束
延长
乒乓球
B类
“乒乓”类

发生的情况是,在定义新类时,您失去了对外部作用域的访问,因为它为您提供了自己的作用域

如上所述,要求Sinatra运行
extend Sinatra::Delegator
,它添加了所有已知的方法

考虑到这一过度简化:

module A
  def ping
    "pong"
  end
end

ping # => throws NoMethodError
extend A
ping # => "pong"

class B
  def my_ping
    ping
  end
end

B.new.my_ping # => throws NoMethodError
为什么??因为Ruby的范围规则

您可以通过向外部范围传递引用来解决这个问题

module A
  def ping
    "pong"
  end
end

extend A
ping # => "pong"

class B
  class << self
    attr_accessor :app

    def my_ping
      app.ping
    end
  end
end

B.app = self
B.my_ping # => "pong"
模块A
德平
“乒乓球”
结束
结束
延长
乒乓球
B类
“乒乓”类

或者
C类
,然后在
self中省略
Sinatra::Application
。我认为f
也可以。但是你能解释一下这里发生了什么吗
settings
是一种
Sinatra::Application
的方法,对吗?为什么可以从顶级方法访问它?或者
classc
,然后在
self中省略
Sinatra::Application
。我认为f
也可以。但是你能解释一下这里发生了什么吗
settings
是一种
Sinatra::Application
的方法,对吗?为什么可以从顶级方法访问它?