Ruby on rails 在Rails ActiveRecord中分配给布尔字段时,如何转换值?
我问题的简短版本 在Rails ActiveRecord中,如果我有一个布尔字段,并将其赋值为“Ruby on rails 在Rails ActiveRecord中分配给布尔字段时,如何转换值?,ruby-on-rails,activerecord,boolean,Ruby On Rails,Activerecord,Boolean,我问题的简短版本 在Rails ActiveRecord中,如果我有一个布尔字段,并将其赋值为“abc”或2,那么它会立即转换为false。值1被转换为true,而nil保持为nil。为什么会这样?在哪里可以找到解释这种行为的Rails文档(或Ruby文档) 我的问题的长篇版本 我很难理解Rails是如何处理为Rails模型中的Boolean字段赋值的尝试的。例如,假设我有一个网站模型,它有一个字符串字段,名为:domain,还有一个布尔字段,名为:can\u ssl 我的迁移如下所示: cla
abc
”或2
,那么它会立即转换为false
。值1
被转换为true
,而nil
保持为nil
。为什么会这样?在哪里可以找到解释这种行为的Rails文档(或Ruby文档)
我的问题的长篇版本
我很难理解Rails是如何处理为Rails模型中的Boolean
字段赋值的尝试的。例如,假设我有一个网站
模型,它有一个字符串
字段,名为:domain
,还有一个布尔
字段,名为:can\u 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
因此,根据我迄今为止所做的工作,我认为我可以得出以下结论:
- 将值
或1
分配给true
字段时,该值将立即转换为布尔值
,然后进行分配true
- 将
赋值给nil
字段时,该字段实际上被赋值为Boolean
nil
- 当分配任何其他值(例如
或任何非字符串
的数字)时,该值将立即转换为1
假
我很难在Rails中找到
Boolean
字段类型的文档,这可以让我对此进行澄清。这是在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_值定义为
#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”之所以存在,是因为MySql和PostgreSql等流行的DBMS分别将布尔值存储为0/1和“f”/“t”
值得注意的是,这与Ruby/Rails中通过“if”测试的内容之间的区别,即“truthy”或“falsy”值(“falsy”值将通过if测试,“truthy”值将通过测试)
在Ruby中,
nil
和false
都是“falsy”,其他任何东西(包括0、空数组、空字符串、空哈希等)都是“truthy”。因此,在ruby中被视为truty/falsy的内容与保存为布尔数据库列的true/false的内容之间存在着巨大的差异。这是ruby的东西,而不是Rails的东西。布尔值是“真实的”。这里有一篇非常有用的文章 布尔列的行为随两次提交而更改:
- (2014-10-17)
- (2015-01-04)
module ActiveRecord
module Type
class Boolean < Value # :nodoc:
def type
:boolean
end
private
def cast_value(value)
if value == ''
nil
else
!ConnectionAdapters::Column::FALSE_VALUES.include?(value)
end
end
end
end
end
如果某个值不是空字符串且不在其中,则该值将转换为true
此更改将在Rails 5.0上生效。这不是他问的问题:他问的是“为什么将'abc'保存为布尔列的“false”。“abc”在ruby中是真实的,这似乎是一个矛盾。
module ActiveRecord
module Type
class Boolean < Value # :nodoc:
def type
:boolean
end
private
def cast_value(value)
if value == ''
nil
else
!ConnectionAdapters::Column::FALSE_VALUES.include?(value)
end
end
end
end
end
[false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set