string“true”和“false”为布尔值

我有一个Rails应用程序,我使用jQuery在后台查询我的search视图。 有字段q (search词), start_dateend_dateinternalinternal字段是一个checkbox,我使用is(:checked)方法来构build被查询的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]因为有一个string或者包含“真”或“假”,我需要把它转换为布尔值。 当然,我可以这样做:

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

但是我认为必须有更多的Ruby'ish方式来解决这个问题! 不在吗?

就我所知,没有任何方法可以将string转换为布尔值,但是如果string只包含'true''false' ,则可以将方法缩短为以下值:

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

ActiveRecord提供了一个干净的方式来做到这一点。

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

ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES具有True值的所有明显的表示forms作为string。

安全通知

请注意,这个答案仅仅适用于下面列出的其他用例,而不是问题中的答案。 虽然大多是固定的,但是由于将用户input作为YAML加载而导致了许多与YAML相关的安全漏洞 。


我用来将string转换为YAML.load技巧是YAML.load ,例如:

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

YAML布尔接受相当多的真/假string:

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

另一个用例

假设你有一个像这样的configuration代码:

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

在命令行中:

 $ export ETC_SOMETHING=false 

现在,由于ENVvariables是一次内部的string,因此config.etc.something的值将是string"false" ,并且将错误地计算为true 。 但是,如果你这样做:

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

这一切都会好起来的。 这与从.yml文件加载configuration兼容。

没有任何内置的方式来处理这个(虽然actionpack可能有一个帮手)。 我会build议这样的事情

 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而不是假/真正的文字:

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

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 

所以你可以在这样的初始化器中创build自己的to_b (或to_boolto_boolean )方法:

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

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

这个gem实现了String,Integer,Symbol和NilClass类的#to_b方法。

 params[:internal].to_b 

我不认为这样的东西是在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

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

看看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 

也许str.to_s.downcase == 'true'的完整性。 那么即使str是零或0,也不会有任何崩溃。

你可以考虑只添加internal到你的url,如果它是真的,那么如果checkbox没有被选中,并且你不追加它, params[:internal]将是nil ,在Ruby中它的值为false。

我不熟悉你正在使用的具体jQuery,但有没有比手动构build一个URLstring更清晰的方式来调用你想要的? 你有没有看过$get$ajax

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

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

我很惊讶没有人发布这个简单的解决scheme。 那就是如果你的string是“真”还是“假”。

 def to_boolean(str) eval(str) end