0

我正在开发一个通过 RestClient 连接到后端数据存储(也是 ruby​​,而不是 rails)的 rails 应用程序。我刚刚将此方法添加到 rails 应用程序的后端 api 类,以从后端获取文件大小:

class Backend < ActiveResource::Base
  def self.file_size(file_key)
    RestClient.get("#{SERVER_URL}/files/#{file_key}/size")
  end
end

而后端对应的代码是:

get '/files/:file_id/size' do
  json_for file.size
end

对于一个示例文件,Backend.file_size(file.key) 返回“198942”,但是当这个属性被保存到数据库中时(在一个整数字段中),它被转换为 int 为 200。

我在rails控制台中玩过这个,输出令人困惑。

test_size = Backend.file_size(file.key)
=> "198942"
control_size = "198942"
=> "198942"

test_size.class
=> String
control_size.class
=> String

test_size.bytes.to_a
=> [49, 57, 56, 57, 52, 50]
control_size.bytes.to_a
=> [49, 57, 56, 57, 52, 50]

test_size.to_i
=> 200
control_size.to_i
=> 198942

Integer(test_size)
=> 198942
Integer(control_size)
=> 198942

test_size.to_s.to_i
=> 200
control_size.to_s.to_i
=> 198942

test_size.tr('^A-Za-z0-9', '').to_i
=> 198942

我还检查了编码,其余响应是 US-ASCII,但是当 force_encoded 为 UTF-8 时,它的行为是相同的。奇怪的是,test_size 在 Integer 和 tr sub 下正确转换以删除任何非打印字符,但字节内容与控制字符串相同。

我最终找到了这个问题的根源(在下面回答),但如果有人以前有过这种经验,以及是否有人能洞察为什么 RestClient 会以这种方式响应(在这种特殊情况下),我会很感兴趣。

4

1 回答 1

3

经过更多调查(查看 test_size 和 control_size 的公共方法),我发现来自 RestClient 的返回值是一个 RestClient::Response,即使它看起来像 String 一样。

test_size.is_a?(String)
=> true
test_size.is_a?(RestClient::Response)
=> true

test_size.code
=> 200

这让我感到非常意外的行为(尽管我知道通过休息客户端而不是 JSON 发送裸值有点不寻常),如果有人知道 RestClient::Response 对象如何/为什么看起来很奇怪,我会很好奇显示为 String 的混合对象,似乎已经猴子修补了一堆 String 方法(但不是全部 - 例如tr)。

我只是通过重构前端和后端 API 类来传递 JSON 对象来解决这个问题。

前端重构代码:

class Backend < ActiveResource::Base
  def self.file_size(file_key)
    JSON.parse(RestClient.get("#{SERVER_URL}/files/#{file_key}/size"))
  end
end

后端代码:

get '/files/:file_id/size' do
  json_for file.size
end

class File
  def size
    {
      size: size
    }
  end
end
于 2013-11-15T00:58:44.733 回答