Rails:我在哪里放置我的API方法?

JVG*_*JVG 3 ruby model-view-controller ruby-on-rails

我对Rails很新,而且我做一些简单的事情,比如创建一个API调用,我有点不知所措.我已经建立了一个/reports有这个控制器的路线:

class ReportsController < ApplicationController

  @client = # Api-accessing gem

  @all_reports = []

  def self.request_report

    begin
      puts "Step 1:"
      step1 = @client.request_report(opts = {"max_count" => 1})
      step1_result = step1.parse
      puts "Done!"
      puts step1_result

    rescue Excon::Errors::ServiceUnavailable => e
      puts "Didn't work"
      logger.warn e.response.message
      retry
    end
  end # End request_report

  request_report

end
Run Code Online (Sandbox Code Playgroud)

这在我第一次加载/reports路由时正确调用外部API ,但是当我刷新页面时,代码不会重新运行.

也许我误解了控制器的用途?我是不是想把这段代码放到其他地方?或者是否存在缓存问题?

max*_*max 7

控制器的唯一的公共API是行动,这在HTTP请求做出响应.在您的情况下,get "/reports" => "reports#request_report"是与行动相对应的路线request_report.

但是,操作是实例方法,而不是类方法:

class ReportsController
  def request_report # self.request_report would make this a class method!
    # @todo get reports from somewhere and
    # return some sort of response.
  end

  # any method call here happens when the class is evaluated.
end
Run Code Online (Sandbox Code Playgroud)

您将该操作声明为类方法,然后在评估ReportsController类时调用它.很抱歉,但关于控制器的一切都是错误的.

Rails惯例是调用该动作index.

Rails中的控制器只能由路由器(或您的测试框架)实例化.因此,他们肯定是放置可用的钻头和凸起的错误位置.如果你曾经看到有人在做ReportsController.new.foo或者ReportsController.foo当场解雇他们.

那么你在哪里放置外部API调用?

如果它是一个非常简单的一次性,你可以在控制器中将它放在私有方法中.

有些地方会在模型层上调用API - 但这是有争议的,因为ActiveRecord模型已经被赋予了权力和责任的鳃.

一个对我有用的解决方案是Service Objects.它们易于测试并且具有明确的单一责任.

class RequestReportService
  def initalize(client)
    @client = client
  end 
  def call(opts = {})
   begin
      return @client.request_report(opts.merge("max_count" => 1))
    rescue Excon::Errors::ServiceUnavailable => e
      nil
    end
  end
end

class ReportsController
  def index
    @reports = RequestReportService.new(@client).call
  end
end
Run Code Online (Sandbox Code Playgroud)