ActiveRecord:select正在弄乱我的数据类型

时间:2009-12-09 05:02:10

标签: ruby-on-rails ruby activerecord

所以我有这个非常简单的片段。

Topic.all(:select => 'count(*) as cnt')[0].cnt   # behaves the same on all models
"500"  # What, a string? 

似乎由于某种原因,ActiveRecord将计数强制转换为字符串。实际上,我注意到它将原始对象中缺少的选择列表中的所有内容强制转换为字符串。

为什么会这样?

什么是修复此问题的猴子补丁,以便按预期工作?

:我不想使用Topic.count,我有一些棘手的分组并选择我需要做的。

仅供参考使用ActiveRecord 2.3.5

证明信息在原始连接中:

ree-1.8.7-2009.10 > r = ActiveRecord::Base::connection.raw_connection.query(
     "select 1").fetch_field.type == Mysql::Field::TYPE_LONGLONG
 => true
ree-1.8.7-2009.10 > r = ActiveRecord::Base::connection.raw_connection.query(
    "select 'a'").fetch_field.type == Mysql::Field::TYPE_VAR_STRING
 => true

使用Stmt API时,您可以自动获得正确类型的内容

ree-1.8.7-2009.10 > s = ActiveRecord::Base::connection.raw_connection.stmt_init
 => #<Mysql::Stmt:0xbd083dc>
ree-1.8.7-2009.10 > s.prepare("select 1, 'hello'")
 => #<Mysql::Stmt:0xbd083dc>
ree-1.8.7-2009.10 > s.execute
 => #<Mysql::Stmt:0xbd083dc>
ree-1.8.7-2009.10 > s.fetch
 => [1, "hello"]
ree-1.8.7-2009.10 >

但是...... Active Record MySql Adapter使用返回字符串的查询API。

ree-1.8.7-2009.10 > cnn.query("select 1,2,3 union all select 1,2,3").each{|r| p r}
["1", "2", "3"]
["1", "2", "3"]

2 个答案:

答案 0 :(得分:0)

实际上可能是因为没有简单的方法来假设值是什么,因此String是“安全的”。选择中未映射到列的任何内容都无法针对类型进行内省。

答案 1 :(得分:-1)

问题是MySQL。当MySQL返回结果集时,结果集没有关于列的类型的信息。 ActiveRecord只能做到最好:将所有内容都视为字符串。

ActiveRecord可以将从“普通”查询(SELECT id FROM topics)返回的列视为正确的类型,因为ActiveRecord向DB询问了列的类型。