0

我是 Ruby 和 Sinatra 的新手,并试图访问闭包 ( ) 中的记录器对象。EM.run do .. end

这是从工作代码中提取的,其中带有消息“LOGGER IS NOT ACCESSIBLE HERE”的日志记录语句给出编译错误。

class Connection
  def get_updates
   logger.info "LOGGER IS NOT ACCESSIBLE HERE 1"
  end
end

class Streamer < Sinatra::Base
  def stream
    logger.info "Inside stream"
    EM.run do
     logger.info "LOGGER IS NOT ACCESSIBLE HERE 3"
     Connection.new.get_updates

     EM::PeriodicTimer.new(10) do
      logger.info "LOGGER IS NOT ACCESSIBLE HERE 4"
     end
   end
  end
end
get '/' do
  logger.info "loading data"
  Streamer.new.stream  
end

从我发现 Sinatra 使用的文档env['rack.logger']中。我们如何在上述代码中的非 Sinatra 类中使用相同的类,如 Connection 和 Streamer?

4

1 回答 1

1

实际上是一个非常有趣的问题。事实证明,该logger字段实际上并不是一个变量 - 它是Sinatra::Base. 因此,当您执行Sinatra::Base对象范围内的代码时,您只需键入它即可调用logger,它将返回记录器对象。

由于它是Sinatra::Base对象的一部分,因此在对象范围内是不可见的Connection

现在我们要结束简单的 Ruby 内容,是时候进入更高级的部分了。

更有趣的部分是当您从该EM.run do部分中调用它时。你不能在那里使用 logger 的原因是因为这些块不是在对象的范围内执行的Streamer,它们是由 eventmachine 本身使用类似的东西在其他范围内执行的instance_eval-class_eval这篇文章展示了一个很好的例子,说明如何instance_eval在像EM这样的DSL。

这也是为什么logger可以从get '/'块中访问该方法的原因 - Sinatra 将在具有loggerusing 方法的对象范围内执行此块instance_eval

为了做你想做的事,你可以尝试创建一个包含记录器的局部变量:

class Streamer < Sinatra::Base
  def stream
    # This will create a local variable called logger that will
    # save whatever is returned by the logger method
    logger = self.logger

    logger.info "Inside stream"
    EM.run do
     logger.info "This should now be accessible"
     Connection.new.get_updates

     EM::PeriodicTimer.new(10) do
      logger.info "This should now be accessible"
     end
   end
  end
end

这仍然不能解决从您的Connection班级登录的问题。做到这一点的方法是要么使用全局日志变量(坏主意),要么在你这样做时传入记录器变量Connection.new(不是惊人的想法,但比全局更好)。

于 2012-12-13T14:53:36.677 回答