检查Ruby中的空性 : nil? vs blank? vs empty? vs presence?

109 阅读4分钟

仅仅是 "如果 "可能是不够的

if false 或者 不会执行相应的条件,因为 和 被认为是虚假的值。if nil false nil

换句话说,如果你把nilfalse 铸成布尔值,它将返回false所有其他类型的值在Ruby中都被认为是真实的。一个快速的破解方法(不仅适用于Ruby,也适用于JavaScript)是在变量前加一个双感叹号。

!!nil        # nil => false  
!!false      # boolean false => false  
!!true       # boolean true => true  
!!0          # number zero => true  
!!42         # number other than zero => true  
!!""         # empty string => true  
!!" "        # spaces-only string => true  
!!"sth"      # non-empty string => true  
!![]         # empty array => true  
!![nil]      # array with empty values => true  
!!['a', 'z'] # non-empty array => true  
!!{}         # empty hash => true  
!!{a: nil}   # hash with empty values => true  
!!{a: 42}    # non-empty hash => true  
!!/regex/    # regex => true  
!!Time.now   # any object => true  

.nil? 是来自Ruby的,检查对象是否真的是nil

这是最简单的部分。在Ruby中,你可以检查一个对象是否为nil,只要在该对象上调用nil? 就可以了......即使该对象是nil。如果你想一想,这是很合乎逻辑的 :)

题外话:在Ruby中,按照惯例,每个以问号结尾的方法都被设计为返回布尔值(真或假)。在JavaScript中,惯例是不同的:通常,这种方法以 "是 "开头(isEmpty,isNumeric,等等)。

nil.nil?        # nil => true  
false.nil?      # boolean false => false  
true.nil?       # boolean true => false  
0.nil?          # number zero => false  
42.nil?         # number other than zero => false  
"".nil?         # empty string => false  
" ".nil?        # spaces-only string => false  
"sth".nil?      # non-empty string => false  
[].nil?         # empty array => false  
[nil].nil?      # array with empty values => false  
['a', 'z'].nil? # non-empty array => false  
{}.nil?         # empty hash => false  
{a: nil}.nil?   # hash with empty values => false  
{a: 42}.nil?    # non-empty hash => false  
/regex/.nil?    # regex => false  
Time.now.nil?   # any object => false  

.empty? 是来自Ruby,它检查大小是否为0

.empty? 是一个Ruby方法,它Hash、Array或String有效。但不是对每个Enumerable。如果大小在0以上,它返回true。对于其他的,它返回NoMethodError

nil.empty?        # nil => NoMethodError  
false.empty?      # boolean false => NoMethodError  
true.empty?       # boolean true => NoMethodError  
0.empty?          # number zero => NoMethodError  
42.empty?         # number other than zero => NoMethodError  
"".empty?         # empty string => true  
" ".empty?        # spaces-only string => false  
"sth".empty?      # non-empty string => false  
[].empty?         # empty array => true  
[nil].empty?      # array with empty values => false  
['a', 'z'].empty? # non-empty array => false  
{}.empty?         # empty hash => true  
{a: nil}.empty?   # hash with empty values => false  
{a: 42}.empty?    # non-empty hash => false  
/regex/.empty?    # regex => NoMethodError  
Time.now.empty?   # custom object => NoMethodError  

.blank? 是来自ActiveSupport

.blank? 来自于奇妙的ActiveSupport。ActiveSupport是Rails的一个依赖项,所以如果你在Rails环境中,你已经有了这个方法,而且是免费的。

上面的NoMethodError ,可能会很烦人。因此,ActiveSupport添加了一个.blank? 方法,它永远不会失败。

警告:对于Rails来说,什么被认为是 "空白 "是有争议的。带有空格的字符串被认为是 "空白",但数字 "0 "则不是。请看这里的列表。

nil.blank?        # nil => true  
false.blank?      # boolean false => true  
true.blank?       # boolean true => false  
0.blank?          # number zero => false  
42.blank?         # number other than zero => false  
"".blank?         # empty string => true  
" ".blank?        # spaces-only string => true  
"sth".blank?      # non-empty string => false  
[].blank?         # empty array => true  
[nil].blank?      # array with empty values => false  
['a', 'z'].blank? # non-empty array => false  
{}.blank?         # empty hash => true  
{a: nil}.blank?   # hash with empty values => false  
{a: 42}.blank?    # non-empty hash => false  
/regex/.blank?    # regex => false  
Time.now.blank?   # custom object => false  

没有更多的错误......但定义什么是 "空白 "的方法是有意见的。所以要特别注意

  • 0.blank? 返回false。在我看来,0应该被认为是一个 "空白 "值。这将与其他语言更加一致。
  • false.blank? 返回true。可能会被视为奇怪或合乎逻辑,取决于你的习惯。
  • [nil, ''].blank? 返回false。空白值的数组不被认为是空白。这一次,我发现它是合乎逻辑的,因为方法 blank 评估的是数组,而不是数组里面的东西。
  • 现在棘手的部分是:[nil].any? 返回false。但是[''].any? 却返回真。这是因为空字符串是真实的。如果你想检查[nil, ''] 是否包含任何有趣的东西,你可以这样做:[nil, ''].all?(&:blank?) 返回真。

.present? 也来自ActiveSupport

.present? 是空白的否定,所以在这里并不奇怪。

nil.present?        # nil => false  
false.present?      # boolean false => false  
true.present?       # boolean true => true  
0.present?          # number zero => true  
42.present?         # number other than zero => true  
"".present?         # empty string => false  
" ".present?        # spaces-only string => false  
"sth".present?      # non-empty string => false  
[].present?         # empty array => false  
[nil].present?      # array with empty values => true  
['a', 'z'].present? # non-empty array => true  
{}.present?         # empty hash => false  
{a: nil}.present?   # hash with empty values => true  
{a: 42}.present?    # non-empty hash => true  
/regex/.present?    # regex => true  
Time.now.present?   # custom object => true  

结论

作为备忘,我把这个决策表放在这里。

方法如果()nil?空?任何?空白?present?(!blank?)
范围红宝石仅限rails
对象所有字符串、数组、哈希可列举全部
nil错误true无方法错误NoMethodErrortrue错误
错误虚假错误无方法错误无方法错误(NoMethodError准确的错误
truetrue错误无方法错误(NoMethodErrorNoMethodError错误true
0true错误无方法错误(NoMethodError无方法错误(NoMethodError错误true
42true错误无方法错误(NoMethodError无方法错误(NoMethodError错误true
""true错误true无方法错误(NoMethodErrortrue错误
""true虚假虚假无方法错误(NoMethodErrortrue错误
"..."true错误错误无方法错误(NoMethodError错误true
[]true错误虚假假的
[无]虚假虚假虚假虚假
['a', 'z']假的错误虚假
{}true假的虚假假的
{ a: nil }假的假的虚假
{ a:42 }假的假的虚假
/regex/false方法错误(NoMethodErrorNoMethodError错误true
时间.现在truefalse方法错误(NoMethodError无方法错误(NoMethodErrorfalsetrue