ruby-on-rails – 在Rails ActiveRecord中分配给布尔字段时如何转换值?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 在Rails ActiveRecord中分配给布尔字段时如何转换值?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我的问题的简短版本

在Rails ActiveRecord中,如果我有一个布尔字段并且我给它分配了类似“abc”或2的东西,那么它会立即转换为false.值1转换为true,nil保持为nil.为什么会这样?我在哪里可以找到解释此行为的Rails文档(或Ruby文档)?

我的问题的长版本

我很难理解Rails如何处理为Rails模型中的布尔字段赋值的尝试.例如,假设我有一个网站模型,其中包含一个名为domain的字符串字段和一个名为can_ssl的布尔字段.

我的迁移看起来像这样:

  1. class CreateWebsites < ActiveRecord::Migration
  2. def change
  3. create_table :websites do |t|
  4. t.string :domain
  5. t.boolean :can_ssl,:default => false
  6.  
  7. t.timestamps
  8. end
  9. end
  10. end

在我的模型文件中,我添加了一些验证规则,所以它看起来像这样:

  1. class Website < ActiveRecord::Base
  2. validates :domain,:presence => true
  3. validates :can_ssl,:inclusion => { :in => [true,false] }
  4. end

很简单.基于我所做的,我期待:can_ssl只能设置为值true或false,而不是其他任何东西.还有其他什么会导致有效吗?是假的.

但是一旦我开始在控制台中玩游戏,我注意到,早在实际的赋值语句中,我提供的值正在重新转换为true或false(或nil).有关如何将值转换为布尔值的规则是什么?

控制台的示例:

  1. w = Website.new
  2. w.domain = 'stackoverflow.com'
  3. w.can_ssl = true
  4. w.can_ssl # => true
  5. w.valid? # => true
  6.  
  7. w.can_ssl = nil
  8. w.can_ssl # => nil
  9. w.valid? # => false (so far so good)
  10.  
  11. w.can_ssl = 'abc'
  12. w.can_ssl # => false (How did 'abc' become the value false?)
  13. w.valid? # => true
  14.  
  15. w.can_ssl = 1
  16. w.can_ssl # => true (I guess it makes sense that 1 casts to true)
  17. w.valid? # => true
  18.  
  19. w.can_ssl = 2
  20. w.can_ssl # => false (But anything other than 1 casts to false?)
  21. w.valid? # => true

所以,根据我迄今所做的工作,我想我可以得出以下结论:

>将值1或true赋给布尔字段时,该值将立即转换为true,然后分配.
>将nil分配给布尔字段时,该字段实际上分配为nil.
>当分配任何其他内容(例如字符串或任何不是1的数字)时,该值将立即转换为false.

我理解正确吗?我错过了什么吗?

我很难在Rails中找到文档中的布尔字段类型,这可以让我对此做出澄清.

解决方法

这是在ActiveRecord的内容中完成的:特别是
  1. ActiveRecord::ConnectionAdapters::Column.value_to_boolean

至少在我的rails版本中(在最近的版本中可能会略有不同).

这是我的版本中的来源

  1. # File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb,line 144
  2. 144: def value_to_boolean(value)
  3. 145: if value.is_a?(String) && value.blank?
  4. 146: nil
  5. 147: else
  6. 148: TRUE_VALUES.include?(value)
  7. 149: end
  8. 150: end

其中TRUE_VALUES定义为

  1. #activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb:10:
  2. TRUE_VALUES = [true,1,'1','t','T','true','TRUE'].to_set

1,“f”和“t”是因为流行的DBMS像MysqL& Postgresql,分别存储为0/1和“f”/“t”.

值得注意的是,这与通过Ruby / Rails中的“if”测试之间的区别,即“truthy”或“falsy”的值(“falsy”值将失败,如果测试,“truthy”值将通过它) .

在Ruby中,nil和false是“falsy”,而字面上的任何其他东西(包括0,空数组,空字符串,空哈希等)都是“真实的”.因此,在ruby中被视为真实/虚假的内容与在布尔数据库列中保存为真/假的内容之间存在巨大差异.

猜你在找的Ruby相关文章