为什么这个ruby字符串将to_i转换为200?

时间:2013-11-15 00:58:45

标签: ruby-on-rails ruby rest rest-client

我正在开发一个rails应用程序,它通过RestClient连接到后端数据存储(也是ruby,而不是rails)。我刚刚将这个方法添加到rails app的后端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子下正确转换以删除任何非打印字符,但字节内容与控制字符串相同。

我最终得到了这个问题的根源(下面的回答),但我感兴趣的是,如果有人之前有这种经历,并且如果有人了解为什么RestClient以这种方式响应(在这种特殊情况下)。 / p>

1 个答案:

答案 0 :(得分:3)

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

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

test_size.code
=> 200

这让我觉得非常意想不到的行为(虽然我知道通过休息客户端而不是JSON发送裸值有点不寻常),如果有人知道RestClient :: Response对象如何/为何如此/我会好奇是一个奇怪的混合对象,表现为一个字符串,似乎猴子修补了一堆字符串方法(但不是全部 - 例如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