我的问题的简短版本
在Rails ActiveRecord中,如果我有一个布尔字段并且我给它分配了类似abc
"或"的东西2
,那么它会立即转换为false
.该值1
将转换为true
,并nil
保持为nil
.为什么会这样?我在哪里可以找到解释此行为的Rails文档(或Ruby文档)?
我的问题的长版本
我很难理解Rails如何处理Boolean
为Rails模型中的字段赋值的尝试.例如,假设我有一个Website
模型,其中包含一个String
被调用:domain
的Boolean
字段和一个被调用的字段:can_ssl
.
我的迁移看起来像这样:
class CreateWebsites < ActiveRecord::Migration def change create_table :websites do |t| t.string :domain t.boolean :can_ssl, :default => false t.timestamps end end end
在我的模型文件中,我添加了一些验证规则,所以它看起来像这样:
class Website < ActiveRecord::Base validates :domain, :presence => true validates :can_ssl, :inclusion => { :in => [true, false] } end
很简单.基于我做了什么,我期待那:can_ssl
只能设置为值true
或false
,而不是其他.还有什么会导致valid?
被false
.
但是一旦我开始在控制台中玩游戏,我注意到,早在实际的赋值语句中,我提供的值正在重铸true
或false
(或nil
).有关如何将值转换为什么规则Boolean
?
控制台的示例:
w = Website.new w.domain = 'stackoverflow.com' w.can_ssl = true w.can_ssl # => true w.valid? # => true w.can_ssl = nil w.can_ssl # => nil w.valid? # => false (so far so good) w.can_ssl = 'abc' w.can_ssl # => false (How did 'abc' become the value false?) w.valid? # => true w.can_ssl = 1 w.can_ssl # => true (I guess it makes sense that 1 casts to true) w.valid? # => true w.can_ssl = 2 w.can_ssl # => false (But anything other than 1 casts to false?) w.valid? # => true
所以,根据我迄今所做的工作,我想我可以得出以下结论:
当分配值1
或true
到Boolean
现场,该值将立即得到铸成true
,然后分配.
分配nil
给Boolean
字段时,实际分配字段nil
.
在分配任何其他内容(例如a String
或任何不是的数字1
)时,该值将立即转换为false
.
我理解正确吗?我错过了什么吗?
我很难Boolean
在Rails中找到文档字段类型,这可以让我对此做出澄清.
这是在ActiveRecord的内容中完成的:特别是
ActiveRecord::ConnectionAdapters::Column.value_to_boolean
至少在我的rails版本中(在最近的版本中可能会略有不同).
这是我的版本中的来源
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 144 144: def value_to_boolean(value) 145: if value.is_a?(String) && value.blank? 146: nil 147: else 148: TRUE_VALUES.include?(value) 149: end 150: end
其中TRUE_VALUES定义为
#activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb:10: TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
1,0,"f"和"t"是因为流行的DBMS像MySql和PostgreSql,它们分别存储为0/1和"f"/"t".
值得注意的是这与通过Ruby/Rails中的"if"测试之间的区别,即"truthy"或"falsy"的值("falsy"值将失败,如果测试,"truthy"值将通过它) .
在Ruby中,nil
并且false
是"虚假的",而字面上的任何其他东西(包括0,空数组,空字符串,空哈希等)都是"真实的".因此,在ruby中被认为是真实/虚假的东西与在布尔数据库列中保存为真/假的内容之间存在巨大的差异.