string“true”和“false”为布尔值
我有一个Rails应用程序,我使用jQuery在后台查询我的search视图。 有字段q
(search词), start_date
, end_date
和internal
。 internal
字段是一个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
现在,由于ENV
variables是一次内部的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_VALUES
和ConnectionAdapters::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_bool
或to_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