【问题标题】:Access Ruby Instance Variable from Included Module从包含的模块访问 Ruby 实例变量
【发布时间】:2016-04-14 00:41:50
【问题描述】:

我有一个包含以下代码的 Sinatra API 文件-

require 'json'
require_relative 'api_logger'

include ApiLogger

get /myapi/:id
 request_params = request.env
 write_log('log message')    
end

然后我有一个包含方法“write_log”的模块-

module ApiLogger

def write_log(message)
 file.write(request['user']+message)
end

但 request['user'] 显示为空白。

那么问题是如何从 ApiLogger 模块中的 Sinatra API 文件访问请求变量?另外,我正在从 API 类创建服务类对象,并在初始化时将请求对象传递给它们。如果服务类只包含“ApiLogger”,模块“ApiLogger”能否访问服务类中的“请求”实例变量?

【问题讨论】:

    标签: ruby sinatra


    【解决方案1】:

    您可以将其作为附加参数传递。 比如:

    require 'json'
    require_relative '../../lib/helpers/api_logger'
    
    include ApiLogger
    
    get /myapi/:id
      request_params = request.env
      write_json_log('log message', request)    
    end
    

    def write_json_log(message, request)
      file.write(request['auth_subject']+message)
    end
    

    【讨论】:

    • 是的,request 对象是路由块的本地对象(getpost 和其他 sinatra DSL 方法),因此它在外部不可见。解决这个问题的最干净的方法是遵循这个答案。
    【解决方案2】:

    我不想将请求对象传递给每个方法。因此,我在所有需要记录的类中将“request_params”设置为全局变量,并在“ApiLogger”中添加了这一行以获取请求对象的值-

    request = instance_variable_get '@request_params'
    

    【讨论】:

    • 使用这样的全局变量是一个非常糟糕的主意。一旦您开始使用可以同时处理多个请求的服务器(了解多线程),您就会遇到奇怪的错误,因为您的全局变量将在第一个请求仍在运行时被第二个请求更新。我强烈建议不要这样做。
    【解决方案3】:

    您几乎就在那里,您所需要的只是将您的模块包含在帮助程序中,以便直接访问请求对象。这是作为独立程序运行的代码的略微修改版本:

    require 'sinatra'
    
    module ApiLogger
      def write_log(message)
        $stdout.write(request.env['sinatra.route'] + message)
      end
    end
    
    helpers do
      include ApiLogger
    end
    
    get '/test' do
      write_log('log message')
    
      'ok'
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-06
      • 1970-01-01
      • 2015-05-25
      • 2015-09-11
      • 2016-05-15
      • 2011-02-20
      • 1970-01-01
      • 2016-09-18
      相关资源
      最近更新 更多