Ruby递归方法需要return子句

时间:2016-03-30 16:13:21

标签: ruby

我可能会错过这里显而易见的,但是这段代码失败了,除非我在return案例中递归调用它时使用Net::HTTPRedirection子句。

  def fetch_headers(limit = REDIRECT_LIMIT)
    # You should choose a better exception.
    raise ArgumentError, 'too many HTTP redirects' if limit == 0
    http = Net::HTTP.new(@uri.host, @uri.port)
    http.use_ssl = true if @uri.scheme == 'https'
    request_uri = @uri.request_uri.nil? ? '/' : @uri.request_uri
    http.request_head(request_uri) do |response|
      case response
      when Net::HTTPSuccess then
        return response
      when Net::HTTPRedirection then
        location = response['location']
        parsed_location = URI.parse location
        @uri = parsed_location.absolute? ? parsed_location : @uri.merge(parsed_location)
        fetch_headers(limit - 1)
      else
        return response.value
      end
    end
  end

来电者方法:

  def perform(link_id)
    link = Link.find(link_id)
    url = link.url =~ /^http/ ? link.url : "http://#{link.url}"
    @uri = URI.parse url
    headers = fetch_headers
    case headers.content_type
    when /application/
      filename = File.basename(@uri.path)
      link.update title: filename
    when /html/
      response = fetch_page
      page = Nokogiri::HTML(response)
      link.update title: page_title(page), description: page_description(page)
    else
      logger.warn "URL #{url} with unknow mime-type: #{headers.content_type}"
    end
  end

这是我正在运行的规范:

it 'follows the redirects using relative URL' do
  link = create(:link, url: url)
  path = '/welcome.html'
  stub_request(:head, url).to_return(status: 302, body: '',
                                     headers: { 'Location' => path })
  redirect_url = "#{url}#{path}"
  stub_request(:head, redirect_url).to_return(status: 200, body: '',
                                              headers: html_header)
  stub_request(:get, redirect_url).to_return(status: 200, body: title_html_raw,
                                             headers: html_header)

  UrlScrapperJob.perform_now link.id
  link.reload
  expect(link.title).to match(/page title/)
end

以下是fetch_headers方法的结果:

使用return子句#<Net::HTTPOK 200 readbody=true>

没有return子句#<Net::HTTPFound 302 readbody=true>

我期望的结果是HTTPOK 200,因为它应该遵循重定向,直到200 OK。

1 个答案:

答案 0 :(得分:2)

差异是从return函数返回的值。

return作为函数调用的结果返回它的参数。

如果没有显式http.request_head(request_uri, &block),返回值就是http.request_head(request_uri) do |response| case response when Net::HTTPSuccess then response when Net::HTTPRedirection then location = response['location'] parsed_location = URI.parse location @uri = parsed_location.absolute? ? parsed_location : @uri.merge(parsed_location) fetch_headers(limit - 1) else response.value end end.tap { |result| puts result } # ⇐ here 返回的值,这显然会导致无限递归。

您可能想尝试

return

在没有明确{{1}}的情况下检查实际结果是什么。