将字符串“true”和“false”转为布尔值

Posted

技术标签:

【中文标题】将字符串“true”和“false”转为布尔值【英文标题】:String "true" and "false" to boolean 【发布时间】:2011-12-28 12:44:15 【问题描述】:

我有一个 Rails 应用程序,我正在使用 jQuery 在后台查询我的搜索视图。有字段q(搜索词)、start_dateend_dateinternalinternal 字段是一个复选框,我正在使用 is(:checked) 方法构建被查询的 url:

$.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked'));

现在我的问题出在params[:internal],因为有一个包含“true”或“false”的字符串,我需要将其转换为布尔值。我当然可以这样做:

def to_boolean(str)
     return true if str=="true"
     return false if str=="false"
     return nil
end

但我认为必须有一种更 Ruby'ish 的方式来处理这个问题!那里没有……?

【问题讨论】:

【参考方案1】:

据我所知,没有内置的将字符串转换为布尔值的方法, 但如果您的字符串仅由 'true''false' 组成,您可以将您的方法缩短为以下内容:

def to_boolean(str)
  str == 'true'
end

【讨论】:

稍作修改 str == 'true' || str = '1' 也许 str.downcase == 'true' 为了完整性 @AMTourky 不应该是 str == 'true' || str == '1' 带有两个 "==" ? @Lowryder 是的!如果使用默认复选框。【参考方案2】:

ActiveRecord 提供了一种干净的方式来执行此操作。

def is_true?(string)
  ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string)
end

ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES 将所有明显的 True 值表示为字符串。

【讨论】:

更简单,只需使用ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)(来源)apidock.com/rails/v3.0.9/ActiveRecord/ConnectionAdapters/Column/… 是的,在最新版本中! ActiveRecord::Type::Boolean.new.type_cast_from_user("true") => 真 ActiveRecord::Type::Boolean.new.type_cast_from_user("T") => 真 假值列表已移至 Rails 5 中的 ActiveModel::Type::Boolean ActiveModel::Type::Boolean 似乎是一条更合适的路径 - 虽然 ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES 包含“真实”值,但有人可能会争辩说这只是偶然的情况,并且对于该特定值应该被视为真实的值可以包括用例,但不能包括其他用例。另一方面,ActiveModel::Type::Boolean 显然被设计为以通用方式使用。【参考方案3】:

安全通知

请注意,此答案仅适用于下面列出的其他用例,而不适用于问题中的用例。虽然大部分是固定的,但有许多 YAML related security vulnerabilities 是由将用户输入加载为 YAML 引起的。


我用来将字符串转换为布尔值的技巧是YAML.load,例如:

YAML.load(var) # -> true/false if it's one of the below

YAML bool 接受相当多的真/假字符串:

y|Y|yes|Yes|YES|n|N|no|No|NO
|true|True|TRUE|false|False|FALSE
|on|On|ON|off|Off|OFF

另一个用例

假设你有一段这样的配置代码:

config.etc.something = ENV['ETC_SOMETHING']

在命令行中:

$ export ETC_SOMETHING=false

现在由于ENV vars 是代码中的字符串,config.etc.something 的值将是字符串"false",它会错误地计算为true。但如果你这样做:

config.etc.something = YAML.load(ENV['ETC_SOMETHING'])

一切都会好的。这也与从 .yml 文件加载配置兼容。

【讨论】:

如果传递的字符串在您的控制之下,那就太好了。在这个问题的情况下,提供的值来自用户的浏览器,因此,它们应该被认为是不安全的。 YAML 允许您序列化/反序列化任何 Ruby 对象,这有潜在的危险。发生了很多事件:google.com/webhp?q=rails+yaml+vulnerability @Teoulas,我完全同意你的看法。事实上,我正在添加一个通知,这样人们就不会以不安全的方式使用它。【参考方案4】:

没有任何内置的方法来处理这个问题(尽管 actionpack 可能有一个帮助器)。我会建议这样的事情

def to_boolean(s)
  s and !!s.match(/^(true|t|yes|y|1)$/i)
end

# or (as Pavling pointed out)

def to_boolean(s)
  !!(s =~ /^(true|t|yes|y|1)$/i)
end

同样有效的方法是使用 0 和非 0 代替 false/true 文字:

def to_boolean(s)
  !s.to_i.zero?
end

【讨论】:

如果你使用 "!!(s =~ /regex_here/)",则不需要保护 "s and ...",因为 "nil =~ /anything/" 返回 nil。 确实如此。我添加了它,但也保留了旧的,因为我认为.match 更容易阅读。【参考方案5】:

ActiveRecord::Type::Boolean.new.type_cast_from_user 根据 Rails 的内部映射 ConnectionAdapters::Column::TRUE_VALUESConnectionAdapters::Column::FALSE_VALUES 执行此操作:

[3] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("true")
=> true
[4] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("false")
=> false
[5] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("T")
=> true
[6] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("F")
=> false
[7] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("yes")
DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("yes") to a boolean column. Currently this value casts to `false`. This will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`. (called from <main> at (pry):7)
=> false
[8] pry(main)> ActiveRecord::Type::Boolean.new.type_cast_from_user("no")
DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("no") to a boolean column. Currently this value casts to `false`. This will change to match Ruby's semantics, and will cast to `true` in Rails 5. If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`. (called from <main> at (pry):8)
=> false

因此,您可以在这样的初始化程序中创建自己的 to_b(或 to_boolto_boolean)方法:

class String
  def to_b
    ActiveRecord::Type::Boolean.new.type_cast_from_user(self)
  end
end

【讨论】:

它是 Rails 5 中的 ActiveRecord::Type::Boolean.new.cast(value)(参见下面的 CWitty)【参考方案6】:

您可以使用wannabe_bool gem。 https://github.com/prodis/wannabe_bool

此 gem 为 String、Integer、Symbol 和 NilClass 类实现了 #to_b 方法。

params[:internal].to_b

【讨论】:

【参考方案7】:

在 Rails 5 中,您可以使用 ActiveRecord::Type::Boolean.new.cast(value) 将其转换为布尔值。

【讨论】:

请注意,ActiveRecord::Type::Boolean.new.cast("42") 返回 true【参考方案8】:

为了完整起见,可能是str.to_s.downcase == 'true'。那么即使str 为 nil 或 0,也不会崩溃。

【讨论】:

【参考方案9】:

我不认为 Ruby 内置了类似的东西。您可以重新打开 String 类并在那里添加 to_bool 方法:

class String
    def to_bool
        return true if self=="true"
        return false if self=="false"
        return nil
    end
end

然后你可以在项目的任何地方使用它,像这样:params[:internal].to_bool

【讨论】:

我绝对不想让to_bool 函数返回nil;这似乎是错误的。其他转换函数不这样做:"a".to_i 返回0,而不是nil【参考方案10】:

查看Virtus的源代码,我可能会这样做:

def to_boolean(s)
  map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])]
  map[s.to_s.downcase]
end

【讨论】:

【参考方案11】:

您可以考虑仅将internal 附加到您的网址(如果它为真),那么如果未选中复选框并且您不附加它params[:internal] 将是nil,它在Ruby 中的计算结果为假。

我对您使用的特定 jQuery 不是很熟悉,但是有没有比手动构建 URL 字符串更简洁的方法来调用您想要的内容?你看过$get$ajax吗?

【讨论】:

【参考方案12】:

您可以添加到 String 类以具有 to_boolean 的方法。然后你可以做 'true'.to_boolean 或 '1'.to_boolean

class String
  def to_boolean
    self == 'true' || self == '1'
  end
end

【讨论】:

【参考方案13】:

我很惊讶没有人发布这个简单的解决方案。也就是说,如果您的字符串将是“真”或“假”。

def to_boolean(str)
    eval(str)
end

【讨论】:

那是因为这个解决方案是一个安全灾难。 :D 这个解决方案的问题是用户输入 - 如果有人输入 to_boolean("ActiveRecord::Base.connection.execute('DROP TABLE *')") ,它会破坏你的数据库(并返回真!)。玩得开心:D 好点。我没有考虑上下文。我在想最少数量的字符来实现。 :) 上述漏洞的简单修复:bool = nil; bool = eval(str) if ["true", "false"].include?(str) 只是想为了澄清起见我应该添加。

以上是关于将字符串“true”和“false”转为布尔值的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript - 使用JSON.parse()方法将字符串的‘false‘和‘true‘转换成布尔值

javascript基础:逻辑运算符

Pandas 映射到 TRUE/FALSE 作为字符串,而不是布尔值

javascript中几种为false的值

如何将“False”字符串转换为布尔值 false? [复制]

将字符串“true”/“false”转换为布尔值[duplicate]