我正在开发一个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>
答案 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