Rails 3迁移:布尔值(mysql vs postgreSQL)

5

我正在尝试在我的论坛主题上添加“粘性”选项。这是我的迁移文件的样子:

  def self.up
    add_column :topics, :sticky, :boolean, :null => false, :default => false
  end

  def self.down
    remove_column :topics, :sticky
  end

这在本地mysql上运行得非常完美,但当我将更改推送到使用PostgreSQL的heroku时,在控制台使用时会出现以下情况。

>> t.sticky
=> "f"
>> t.sticky.class
=> String
>> t.sticky = true
=> true
>> t.sticky.class
=> TrueClass

为什么这个属性的默认值是字符串类型?

编辑: 如果我保存该对象,它不会改变 sticky 属性,即仍然为 "f"。


我在我的本地Postgres或Heroku上没有看到那种行为。我正在使用Rails 3.0.7和pg gem的0.11.0版本。顺便说一句,我强烈建议在开发机器上本地使用Postgres。Postgres和mysql之间有许多差异(例如group by、大小写敏感等),即使这不是其中之一(或不应该是),最终你也会遇到某些问题。 - Rob Davis
3个回答

4
在psql中,布尔值显示为tf。根据DB驱动程序的不同,它们会被转换为布尔值或保留其字符串表示形式。
PHP中的PDO驱动程序也是如此。 (或者以前是这样的...我模糊地记得在最新版本中它不再这样做。)

2
我明白了。你有什么想法,为什么Rails不会自动将它们转换为布尔值? - Marjan
1
那将是一个很好的问题/错误报告给RoR开发人员。 :-) - Denis de Bernardy

3
除非您发现RoR或数据库驱动程序中的错误(如Denis所建议的),否则您可以定义(覆盖)读取器访问器,如下所示:
def sticky
  ! [false, nil, 'f'].include?( self[:sticky] )
end

这将把已知的“false”值转换为真正的Ruby布尔值。

我记得至少有两个gem可以连接到PostgreSQL数据库。也许你可以使用另一个?

而且你确定数据库中的列没有被定义为字符串吗?我知道在你的迁移中它是布尔型的,但也许在某些地方出了问题?


我已经很久没有使用Ruby的PostgreSQL驱动程序了,但我似乎记得TRUE和FALSE分别作为字符串“t”和“f”返回。这真是让人恼火,因为其他语言的PostgreSQL绑定正确地将它们映射到其本机布尔数据类型。我刚刚查看了https://bitbucket.org/ged/ruby-pg/src/b5361e087db3/ext/pg.c,似乎Ruby驱动程序的状态没有改变。需要检查Pg的BOOLOID OID,并返回Qtrue或Qfalse。 - Sean
我正在使用ruby-postgres(0.7.9.20080128)并且我的模型中有一些应该是布尔值的地方。也许在我这种情况下是因为Rails 1.2.6。旧的gem + 旧的Rails = 成功?;-) - Arsen7
可能吧。我也完全不介意错了(并且很高兴被证明是错误的!),但我没有在本地的ruby-pg驱动程序中看到PostgreSQL的bool oid和Ruby bool类型之间的类型映射(我只花了2分钟浏览它)。我猜测,但假设Rails中的其他东西正在进行转换。 - Sean

1

我不确定问题出在哪里,但我刚刚回滚了迁移并再次运行它,这次成功了。我把这个放在这里,以防其他人遇到类似的问题。

感谢你们的帮助。


那么这可能是列使用了错误的类型创建? - Arsen7
很有可能,尽管我不确定为什么。我什么都没改,只是回滚了一步,然后再次运行迁移。 - Marjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接