Ruby: 如何将字符串转换为布尔值

我有一个值,它将是四个值之一: boolean true、 boolean false、字符串“ true”或字符串“ false”。如果字符串是一个字符串,我希望将它转换为一个布尔值,否则不要修改它。换句话说:

“真实”应该变成真实

“假的”应该变成假的

应该保持真实

假的就应该是假的

206205 次浏览
if value.to_s == 'true'
true
elsif value.to_s == 'false'
false
end
h = { "true"=>true, true=>true, "false"=>false, false=>false }


["true", true, "false", false].map { |e| h[e] }
#=> [true, true, false, false]

可以使用像 https://rubygems.org/gems/to_bool这样的 gem,但是可以很容易地使用正则表达式或三进制在一行中编写它。

正则表达式例子:

boolean = (var.to_s =~ /^true$/i) == 0

三元例子:

boolean = var.to_s.eql?('true') ? true : false

Regex 方法的优点是,正则表达式是灵活的,可以匹配各种各样的模式。例如,如果您怀疑 var 可能是“ True”、“ False”、“ T”、“ F”、“ t”或“ f”中的任何一个,那么您可以修改 regex:

boolean = (var.to_s =~ /^[Tt].*$/i) == 0
def true?(obj)
obj.to_s.downcase == "true"
end

虽然我喜欢哈希方法(我过去也用它来做类似的事情) ,但是考虑到你只关心匹配真值——因为其他的都是假的——你可以检查数组中是否包含:

value = [true, 'true'].include?(value)

或者其他价值观是否可以被认为是真实的:

value = [1, true, '1', 'true'].include?(value)

如果你原来的 value可能是混合情况,你必须做其他事情:

value = value.to_s.downcase == 'true'

但是,对于你的问题的具体描述,你可以用最后一个例子作为你的解决方案。

在 Rail 中,我以前做过类似的事情:

class ApplicationController < ActionController::Base
# ...


private def bool_from(value)
!!ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
end
helper_method :bool_from


# ...
end

如果您试图像 Rails 对待数据库那样匹配布尔字符串比较,那么这样做很好。

如果你使用 Rails 5,你可以做 ActiveModel::Type::Boolean.new.cast(value)

在 Rails 4.2中,使用 ActiveRecord::Type::Boolean.new.type_cast_from_user(value)

这种行为稍有不同,在 Rails 4.2中,会检查真值和假值。在 Rails 5中,只有 false 值被检查-除非值为 nil 或匹配 false 值,否则它被假定为 true。假值在两个版本中是相同的: FALSE _ VALUES = [ FALSE,0,“0”,“ f”,“ F”,“ FALSE”,“ FALSE”,“ OFF”,“ OFF”]

Rails5来源: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb

我经常使用这种模式来扩展 Ruby 的核心行为,使得将任意数据类型转换为布尔值变得更加容易,这使得处理各种 URL 参数变得更加容易,等等。

class String
def to_boolean
ActiveRecord::Type::Boolean.new.cast(self)
end
end


class NilClass
def to_boolean
false
end
end


class TrueClass
def to_boolean
true
end


def to_i
1
end
end


class FalseClass
def to_boolean
false
end


def to_i
0
end
end


class Integer
def to_boolean
to_s.to_boolean
end
end

假设你有一个参数 foo,它可以是:

  • 一个整数(0为假,其他所有为真)
  • 真布尔值(真/假)
  • 字符串(“ TRUE”、“ FALSE”、“0”、“1”、“ TRUE”、“ FALSE”)
  • 没有

你可以调用 foo.to_boolean来完成剩下的工作,而不是使用一堆条件句。

在 Rails 中,我在几乎所有的项目中都将其添加到名为 core_ext.rb的初始化器中,因为这种模式非常常见。

## EXAMPLES


nil.to_boolean     == false
true.to_boolean    == true
false.to_boolean   == false
0.to_boolean       == false
1.to_boolean       == true
99.to_boolean      == true
"true".to_boolean  == true
"foo".to_boolean   == true
"false".to_boolean == false
"TRUE".to_boolean  == true
"FALSE".to_boolean == false
"0".to_boolean     == false
"1".to_boolean     == true
true.to_i          == 1
false.to_i         == 0

不要想太多:

bool_or_string.to_s == "true"

那么,

"true".to_s == "true"   #true
"false".to_s == "true"  #false
true.to_s == "true"     #true
false.to_s == "true"    #false

如果您担心大写字母,还可以添加“ . downcase”。

在一个 Rails 5.1应用程序中,我使用了构建在 ActiveRecord::Type::Boolean之上的这个核心扩展。当我从 JSON 字符串反序列化布尔值时,它非常适合我。

Https://api.rubyonrails.org/classes/activemodel/type/boolean.html

# app/lib/core_extensions/string.rb
module CoreExtensions
module String
def to_bool
ActiveRecord::Type::Boolean.new.deserialize(downcase.strip)
end
end
end

初始化核心扩展

# config/initializers/core_extensions.rb
String.include CoreExtensions::String

Rspec

# spec/lib/core_extensions/string_spec.rb
describe CoreExtensions::String do
describe "#to_bool" do
%w[0 f F false FALSE False off OFF Off].each do |falsey_string|
it "converts #{falsey_string} to false" do
expect(falsey_string.to_bool).to eq(false)
end
end
end
end

我有个小窍门。JSON.parse('false')将返回 falseJSON.parse('true')将返回 true。但是这对 JSON.parse(true || false)不起作用。所以,如果你使用类似 JSON.parse(your_value.to_s)的东西,它应该实现你的目标,在一个简单但粗糙的方式。

在 Rails 中,我更喜欢使用 ActiveModel::Type::Boolean.new.cast(value),正如在这里的其他答案中提到的那样

但当我写普通的 Ruby lib。然后我使用了一个技巧,JSON.parse(标准 Ruby 库)将字符串“ true”转换为 true,将“ false”转换为 false。例如:

require 'json'
azure_cli_response = `az group exists --name derrentest`  # => "true\n"
JSON.parse(azure_cli_response) # => true


azure_cli_response = `az group exists --name derrentesttt`  # => "false\n"
JSON.parse(azure_cli_response) # => false

实际应用中的例子:

require 'json'
if JSON.parse(`az group exists --name derrentest`)
`az group create --name derrentest --location uksouth`
end

根据 Ruby2.5.1确认

在 Rails 5中工作

ActiveModel::Type::Boolean.new.cast('t')     # => true
ActiveModel::Type::Boolean.new.cast('true')  # => true
ActiveModel::Type::Boolean.new.cast(true)    # => true
ActiveModel::Type::Boolean.new.cast('1')     # => true
ActiveModel::Type::Boolean.new.cast('f')     # => false
ActiveModel::Type::Boolean.new.cast('0')     # => false
ActiveModel::Type::Boolean.new.cast('false') # => false
ActiveModel::Type::Boolean.new.cast(false)   # => false
ActiveModel::Type::Boolean.new.cast(nil)     # => nil

接近已经发布的内容,但没有多余的参数:

class String
def true?
self.to_s.downcase == "true"
end
end

用途:

do_stuff = "true"


if do_stuff.true?
#do stuff
end

这个函数适用于任何输入:

def true?(value)
![false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"].include? value
end

那么你就有了:

true?(param) #returns true or false