字符串"true"和"false"为布尔值

dav*_*idb 82 ruby jquery ruby-on-rails ruby-on-rails-3

我有一个Rails应用程序,我正在使用jQuery在后台查询我的搜索视图.有字段q(搜索词)start_date,end_dateinternal.该internal字段是一个复选框,我正在使用该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'));
Run Code Online (Sandbox Code Playgroud)

现在我的问题是params[:internal]因为有一个字符串要么包含"true"或"false",我需要将它转换为boolean.我当然可以这样做:

def to_boolean(str)
     return true if str=="true"
     return false if str=="false"
     return nil
end
Run Code Online (Sandbox Code Playgroud)

但我认为必须有一种更加Ruby的方式来解决这个问题!不存在......?

cvs*_*erd 129

据我知道有没有内置的铸造字符串布尔值的方式,但如果你的字符串只包含'true''false'您可以缩短你的方法如下:

def to_boolean(str)
  str == 'true'
end
Run Code Online (Sandbox Code Playgroud)

  • 或许str.downcase =='true'表示完整性 (29认同)
  • 只需要一点修改str =='true'|| str ='1' (8认同)

Sat*_*uri 47

ActiveRecord提供了一种干净的方法.

def is_true?(string)
  ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string)
end
Run Code Online (Sandbox Code Playgroud)

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

  • 更简单,只需使用`ActiveRecord :: ConnectionAdapters :: Column.value_to_boolean(string)`(source)http://apidock.com/rails/v3.0.9/ActiveRecord/ConnectionAdapters/Column/value_to_boolean/class (15认同)
  • `ActiveRecord::Type::Boolean.new.type_cast_from_user("true")` => true `ActiveRecord::Type::Boolean.new.type_cast_from_user("T")` => true (6认同)

Hal*_*gür 23

安全通知

请注意,这个简单形式的答案仅适用于下面列出的其他用例,而不是问题中的那个.虽然大多数是固定的,但是有很多与YAML相关的安全漏洞,这些漏洞是由用户输入加载为YAML引起的.


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

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

YAML bool接受了相当多的truthy/falsy字符串:

y|Y|yes|Yes|YES|n|N|no|No|NO
|true|True|TRUE|false|False|FALSE
|on|On|ON|off|Off|OFF
Run Code Online (Sandbox Code Playgroud)

另一个用例

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

config.etc.something = ENV['ETC_SOMETHING']
Run Code Online (Sandbox Code Playgroud)

在命令行中:

$ export ETC_SOMETHING=false
Run Code Online (Sandbox Code Playgroud)

现在,因为ENVvars是代码内部config.etc.something的字符串"false",所以它的值将是字符串,并且它将错误地评估为true.但如果你喜欢这样:

config.etc.something = YAML.load(ENV['ETC_SOMETHING'])
Run Code Online (Sandbox Code Playgroud)

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

  • 如果传递的字符串在您的控制之下,那就太好了。在这个问题的情况下,提供的值来自用户的浏览器,因此,它们应该被认为是不安全的。YAML 允许您序列化/反序列化任何 Ruby 对象,但这有潜在的危险。已经发生了很多事件:https://www.google.com/webhp?q=rails+yaml+vulnerability (2认同)

Mar*_*rth 16

没有任何内置的方法来处理这个问题(虽然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
Run Code Online (Sandbox Code Playgroud)

也可以使用0和非0而不是false/true文字:

def to_boolean(s)
  !s.to_i.zero?
end
Run Code Online (Sandbox Code Playgroud)

  • 如果使用"!!(s =〜/ regex_here /)",则不需要警卫"s和......"因为"nil =〜/ anything /"返回nil. (3认同)

Ale*_*fee 7

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
Run Code Online (Sandbox Code Playgroud)

所以你可以在这样的初始化器中创建自己的to_b(to_bool或者to_boolean)方法:

class String
  def to_b
    ActiveRecord::Type::Boolean.new.type_cast_from_user(self)
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 在Rails 5中是ActiveRecord :: Type :: Boolean.new.cast(value)(请参见下面的CWitty) (2认同)

Pro*_*dis 5

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

这个gem实现了#to_bString,Integer,Symbol和NilClass类的方法.

params[:internal].to_b
Run Code Online (Sandbox Code Playgroud)


小智 5

也许是str.to_s.downcase == 'true'为了完整性。那么即使是 nil 或 0 也不会崩溃str


CWi*_*tty 5

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