Ruby: как преобразовать строку в логическое значение
У меня есть значение, которое будет одной из четырех вещей: boolean true, boolean false, строка "true" или строка "false". Я хочу преобразовать строку в логическое значение, если это строка, в противном случае оставьте ее неизмененной. Другими словами:
"истина" должна стать истиной
"false" должно стать false
истина должна оставаться истиной
false должен оставаться false
10 ответов:
Если вы используете рельсы 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_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
Рельсы 5 Источник: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb
h = { "true"=>true, true=>true, "false"=>false, false=>false } ["true", true, "false", false].map { |e| h[e] } #=> [true, true, false, false]
Я часто использовал этот шаблон для расширения основного поведения 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-ложь, все остальные-истина)
- a true boolean (true/false)
- строка ("true", "false", "0", "1", "правда", "Ложь")
- Нил
вместо того, чтобы использовать кучу условных операторов, вы можете просто позвонить
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, " если вы беспокоитесь о заглавных буквах.
хотя мне нравится хэш-подход (я использовал его в прошлом для подобных вещей), учитывая, что вы действительно заботитесь только о сопоставлении истинных значений - поскольку - все остальное ложно - вы можете проверить включение в массив:
value = [true, 'true'].include?(value)
или если другие значения можно считать истинными:
value = [1, true, '1', 'true'].include?(value)
вам придется делать другие вещи, если ваш оригинал
value
может быть смешанный случай:value = value.to_s.downcase == 'true'
но опять же, для вашего конкретного описания вашей проблемы, вы могли бы вам сойдет с рук этот последний пример в качестве вашего решения.
драгоценный камень, как https://rubygems.org/gems/to_bool может быть использован, но он может быть легко записан в одной строке с помощью регулярного выражения или тернарного.
пример регулярного выражения:
boolean = (var.to_s =~ /^true$/i) == 0
троичная пример:
boolean = var.to_s.eql?('true') ? true : false
преимущество метода регулярных выражений является то, что регулярные выражения являются гибкими и могут соответствовать различные модели. Например, если вы подозреваете, что var может быть любым из "True", "False", "T", "F", " t " или "f", то вы можете изменить регулярное выражение:
boolean = (var.to_s =~ /^[Tt].*$/i) == 0
в rails, я ранее делал что-то вроде этого:
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 для вашей базы данных.