当作为参数传递给另一个方法时,HTTParty::Response 被转换为 Hash
HTTParty::Response is cast into Hash when passed as argument to another method
我有一个发出 api 请求的服务方法,如果响应不正确,它会通知 Bugsnag。它看起来像这样:
def send_request
@response = HTTParty.get(api_endpoint, options)
return JSON.parse(@response.body, symbolize_names: true) if @response.ok?
raise StandardError.new(JSON.parse(@response.body))
rescue StandardError => exception
BugsnagService.notify(exception, @response)
end
我的 BugsnagService#notify
看起来像这样:
class BugsnagService
def self.notify(exception, response = nil, **options)
if response
response_body = if valid_json?(response.body) # Error right here
JSON.parse(response.body)
else
response.body
end
options[:response_body] = response_body
options[:response_code] = response.code
end
# Raising exception in test and development environment, or else the exception will be
# silently ignored.
raise exception if Rails.env.test? || Rails.env.development?
Bugsnag.notify(exception) do |report|
report.add_tab(:debug_info, options) if options.present?
end
end
def self.valid_json?(json_string)
JSON.parse(json_string)
true
rescue JSON::ParserError => e
false
end
end
我在 notify
方法中设置了 response = nil
因为不是每个错误都是 API 错误,所以有时我会调用 BugsnagService.notify(exception)
.
我发现如果我只是像上面代码片段中那样调用它,它会引发一个错误,指出它无法在 Hash
上调用 .body
。不知何故,当我将 @response
传递给 BugsnagService#notify
时,对象从 HTTParty::Response
变为 Hash
。
但是如果我为 **options
参数传递一些东西,它就会起作用。所以我可以这样称呼它:
BugsnagService.notify(exception, @response, { })
我一直在努力弄清楚这一点,但我找不到任何可以解释这一点的东西。我不确定我定义参数的方式是否有问题,或者这是 HTTParty
gem 的一些错误。任何人都可以看到为什么会这样吗?谢谢!
问题是您的 @response
被作为 options
传入,因为 response
可以是 nil
。 double splat 将其转换为散列。
尝试:
def testing(x, y = nil, **z)
puts "x = #{x}"
puts "y = #{y}"
puts "z = #{z}"
end
testing 1, 2, z: 3
#=> x = 1
#=> y = 2
#=> z = {:z=>3}
testing 1, y: 2
#=> x = 1
#=> y =
#=> z = {:y=>2}
testing 1, { y: 2 }, {}
#=> x = 1
#=> {:y=>2}
#=> {}
我建议最好的方法是让 response
成为关键字参数,如:
def self.notify(exception, response: nil, **options)
...
end
这样,您仍然可以根据需要省略或包含响应,并传入后续选项。
我有一个发出 api 请求的服务方法,如果响应不正确,它会通知 Bugsnag。它看起来像这样:
def send_request
@response = HTTParty.get(api_endpoint, options)
return JSON.parse(@response.body, symbolize_names: true) if @response.ok?
raise StandardError.new(JSON.parse(@response.body))
rescue StandardError => exception
BugsnagService.notify(exception, @response)
end
我的 BugsnagService#notify
看起来像这样:
class BugsnagService
def self.notify(exception, response = nil, **options)
if response
response_body = if valid_json?(response.body) # Error right here
JSON.parse(response.body)
else
response.body
end
options[:response_body] = response_body
options[:response_code] = response.code
end
# Raising exception in test and development environment, or else the exception will be
# silently ignored.
raise exception if Rails.env.test? || Rails.env.development?
Bugsnag.notify(exception) do |report|
report.add_tab(:debug_info, options) if options.present?
end
end
def self.valid_json?(json_string)
JSON.parse(json_string)
true
rescue JSON::ParserError => e
false
end
end
我在 notify
方法中设置了 response = nil
因为不是每个错误都是 API 错误,所以有时我会调用 BugsnagService.notify(exception)
.
我发现如果我只是像上面代码片段中那样调用它,它会引发一个错误,指出它无法在 Hash
上调用 .body
。不知何故,当我将 @response
传递给 BugsnagService#notify
时,对象从 HTTParty::Response
变为 Hash
。
但是如果我为 **options
参数传递一些东西,它就会起作用。所以我可以这样称呼它:
BugsnagService.notify(exception, @response, { })
我一直在努力弄清楚这一点,但我找不到任何可以解释这一点的东西。我不确定我定义参数的方式是否有问题,或者这是 HTTParty
gem 的一些错误。任何人都可以看到为什么会这样吗?谢谢!
问题是您的 @response
被作为 options
传入,因为 response
可以是 nil
。 double splat 将其转换为散列。
尝试:
def testing(x, y = nil, **z)
puts "x = #{x}"
puts "y = #{y}"
puts "z = #{z}"
end
testing 1, 2, z: 3
#=> x = 1
#=> y = 2
#=> z = {:z=>3}
testing 1, y: 2
#=> x = 1
#=> y =
#=> z = {:y=>2}
testing 1, { y: 2 }, {}
#=> x = 1
#=> {:y=>2}
#=> {}
我建议最好的方法是让 response
成为关键字参数,如:
def self.notify(exception, response: nil, **options)
...
end
这样,您仍然可以根据需要省略或包含响应,并传入后续选项。