在Rails中处理回调函数的最佳方法

时间:2015-02-25 14:09:06

标签: ruby-on-rails

我有一个包含四个函数的类:GET,PUT,POST和DELETE。我希望在每个PUT,POST和DELETE函数之后调用一个日志函数。

我仍然需要访问我的日志功能中的调用函数中的数据。

在一个理想的世界里,这就是我想要的:

class ApiClient
  after :put, :post, :delete log

  def initialize(url, username = nil, password = nil)
    @connection = Faraday.new(url) do |faraday|
      faraday.basic_auth(username, password) if username
      faraday.request :url_encoded
      faraday.response :logger
      faraday.adapter :net_http
      faraday.use Errors::RaiseError
    end
  end

  def get(path, parameter = nil)
    @connection.get path, parameter
  end

  def post(path, data, headers = {})
    @connection.post path, data, headers
  end

  def put(path, data, headers = {})
    @connection.put path, data, headers
  end

  def delete(path)
    @connection.delete path
  end

  def log
    # handle logging here. will need access to the calling function.
  end
end

2 个答案:

答案 0 :(得分:2)

你可以做另一种方式,不要只调用每个函数的记录器,只包括logger module可以给你记录

module MethodLogger
  def self.included(base)
    methods = base.instance_methods(false) 
    base.class_eval do
      methods.each do |method_name|
        original_method = instance_method(method_name)
        define_method(method_name) do |*args, &block|
          return_value = original_method.bind(self).call(*args, &block)
          Rails.logger.info "<- #{base}##{method_name} #=> #{return_value.inspect}"
          return_value
        end
      end
    end
  end
end

现在在你的班级

class ApiClient
   include MethodLogger
  #rest of the code

 end

现在查看rails日志

答案 1 :(得分:0)

为什么不将数据作为参数传递?

def get(path, parameter = nil)
  result = @connection.get path, parameter
  log result, path, parameter
end

def log(data, *args)
end

阅读评论后编辑

另一个丑陋的解决方案是将接口设为私有,并通过method_missing传递所有调用,您可以在其中实现一些通用逻辑。
例如:

class ApiClient

  def initialize(url, username = nil, password = nil)
    @connection = Faraday.new(url) do |faraday|
      faraday.basic_auth(username, password) if username
      faraday.request :url_encoded
      faraday.response :logger
      faraday.adapter :net_http
      faraday.use Errors::RaiseError
    end
  end


  private


  def get(path, parameter = nil)
    @connection.get path, parameter
  end

  def post(path, data, headers = {})
    @connection.post path, data, headers
  end

  def put(path, data, headers = {})
    @connection.put path, data, headers
  end

  def delete(path)
    @connection.delete path
  end


  def log(method, data, *args)
    puts "logging #{method}, #{args}"
  end


  def method_missing(meth, *args)
    if respond_to?(meth, true)
      result = send(meth, *args)
      log(meth, result, *args)
      result
    else
      super
    end
  end
end