Ruby 不能直接用 1 来判断值为 true 的记录,但在 where 的查询里却可以用 1 查询到值为 true 的记录

Catherine · 2016年01月07日 · 最后由 chenjau 回复于 2016年01月09日 · 1868 次阅读

ruby 1.9.3 和 rails 3.2.14 发现个小问题。 用

Model.where(:enabled => 1)
#可以找到记录


each_record_in_scope do |a|
  next if a.enabled!=1
end
#记录会全部被next掉

打开 irb 也测试了,a.enabled != 1 为 true。

mysql 的话确实是用 1 跟 0 表示真假

MySQL 用一个字节的 integer 来表示 true 和 false,但是这不代表你也应该用 0 和 1 来当 Boolean 用呀。

each_record_in_scope do |a|
  next unless a.enabled
end

Ruby 的 == 会先检测两段对象的类型,相当于某些语言的 ===

其实有一个有意思的现象:

irb(main):039:0> !!1 == true
=> true
irb(main):040:0> !!0 == true
=> true

AcitveRecord 会跟据字段类型,在从数据库取出来以后转换成对应类型的值

#4 楼 赞同 @huacnlee 的说法。参考:

The Active Record connection adapters, classes that implement behavior specific to databases, fetch results as strings and Rails takes care of converting them to other datatypes if necessary, based on the type of the database column. For instance, integer types are cast to instances of Ruby’s Fixnum class, and so on. Even if you’re working with a new instance of an Active Record object, and have passed in constructor values as strings, they will be typecast to their proper type when you try to access those values as attributes. Sometimes you want to be able to read (or manipulate) the raw attribute data without having the column determined typecast run its course first, and that can be done by using the attribute_before_type_cast accessors that are automatically created in your model.

@xworm 你这个例子是不是不能说明问题呀,因为!!0已经是true了,两者比较,自然得到true了。

#6 楼 @killernova 这只是吐一个额外的槽,表达一下 ruby 和某些语言不同 1 != true && 0 != false

同意@huacnlee 的,之前使用 mongo 也是出现这个问题。之前也在帖子中问过。最后是因为这个问题。

可以查询到记录,因为 mysql 里面将 boolean 存为 tinyint 1 或 0 了。where 所构建的查询自然可以查到. 下面的 enabled 之所以有问题,是 activerecord 将数据取出,并解释为 boolean, 此时,意义就不是一回事了. 总之,建议直接跟 orm 打交道。next if a.enabled? 不是更好的多?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号