鉴于我在Rails控制器中有以下设计代码:
class ProfilesController < ApplicationController
def show
@profile = current_user.profile
@content_from_third_party_api = @profile.get_that_third_party_content
end
end
此代码位于views/profiles/show.html.haml
:
%h1
Profile Page!
%h2
Data from 3rd party:
= @content_from_third_party_api.first.title
这个用于#get_that_third_party_content
的设计代码:
def get_that_third_party_content
uri = URI.parse("http://api.somesite.com/imfake/")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
case response.code.to_i
when 200 # the happy path
response
when (400..499)
# What should I do/return here? I have nothing useful to return to the caller.
when (500..599)
# Same goes for here...
end
end
如果给出以下内容,我如何优雅地处理#get_that_third_party_content
中的超时/错误/等:
@content_from_third_party_api
不能为零。如果它没有,我会在整个地方得到NilClass错误#get_that_third_party_content
将不会返回任何内容rescue_from
似乎是一个很好的解决方案,但我不确定这是不是很好答案 0 :(得分:2)
您可能希望在此处使用Faraday之类的内容,因为您可以利用中间件。创建法拉第构建器非常简单,您可以编写中间件来处理所有问题。有超时(只需要它)和异常处理的本机中间件。
鉴于您希望“优雅地”处理这些用例,中间件对我来说似乎是最合理的选择。否则,正如您所指出的,您将在控制器中拥有复杂的分支逻辑。
# lib/requestor.rb
require 'faraday'
require 'faraday_middleware' # optional, but nice: https://github.com/lostisland/faraday_middleware
# This is just one example. There are literally hundreds of ways to use
# Faraday, and the documentation is quite good.
class APIConnector
attr_reader :connection
def initialize(url)
@connection = Faraday.new(url) do |connection|
# Set up your connection here (like response and request objects).
# There are a lot of examples in the Faraday documentation and things
# really depend on the API you are accessing.
#
# You can set things like timeouts, retrys, mashes, rashes, etc.
# Set some options, such as timeouts
connection.options[:timeout] = 10
connection.options[:open_timeout] = 10
end
end
def get(path)
connection.get(path)
end
end
然后在你的控制器中:
class ProfilesController < ApplicationController
def show
@profile = current_user.profile
response = requestor.get('/path')
if response.success?
@third_party_content = response.body
else
# This changes depending on the volatility of your application.
# You might raise an error, show a flash message, kill the
# request, etc. It all depends on the context.
render text: 'API Request failed'
end
end
private
def requestor
@requestor ||= Requestor.new(some_url)
end
end