Tengo un valor que será una de cuatro cosas: booleano verdadero, booleano falso, la cadena "verdadero" o la cadena "falso". Quiero convertir la cadena en un booleano si es una cadena; de lo contrario, déjela sin modificar. En otras palabras:
"verdadero" debería convertirse en realidad
"falso" debería convertirse en falso
la verdad debería permanecer verdad
lo falso debe permanecer falso
ruby
string
boolean
type-conversion
esmeril
fuente
fuente
true
ofalse
o es suficiente si el resultado es Truthy o Falsey-? Si el último, entoncesfalse
ya es falso, y ambostrue
y'true'
son veraces, por lo que el único valor para el que el resultado no es ya correcto es'false'
:if input == 'false' then true else input end
debería hacerlo.!!(if input == 'false' then true else input end)
. El segundo!
convierte el valor de retorno a un booleano que es el opuesto al que desea; el primero!
luego hace la corrección. Este "truco" existe desde hace mucho tiempo. No a todo el mundo le gusta.Respuestas:
fuente
obj.to_s.downcase == 'true'
downcase!
y asignará 1 objeto menos.downcase
duplicará la cadena existente. Cuando Frozen String Literals se convierta en una opción predeterminada de Ruby, esto importará menos.Si usa Rails 5, puede hacerlo
ActiveModel::Type::Boolean.new.cast(value)
.En Rails 4.2, utilice
ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
.El comportamiento es ligeramente diferente, como en Rails 4.2, se verifican el valor verdadero y los valores falsos. En Rails 5, solo se verifican los valores falsos; a menos que los valores sean nulos o coincidan con un valor falso, se asume que es verdadero. Los valores falsos son los mismos en ambas versiones:
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
Rails 5 Fuente: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb
fuente
FALSE_VALUES
en Rails también incluyera "no".ActiveRecord::Type::Boolean::FALSE_VALUES << "no"
a un inicializador.ActiveModel::Type::Boolean.new.cast(value)
distingue entre mayúsculas y minúsculas ... por lo que 'False' se evaluará como verdadero al igual que cualquier otra cadena excepto 'falso'. cadenas vacías por''
defecto a nulo, no falso. ^^ información valiosa proporcionada aquí por @thomasfedb sobre la personalización del inicializadorActiveModel::Type::Boolean.new.cast(nil)
también regresanil
.ActiveRecord::Type::Boolean::FALSE_VALUES
está congelado.Con frecuencia he usado este patrón para extender el comportamiento central de Ruby para facilitar la conversión de tipos de datos arbitrarios en valores booleanos, lo que hace que sea realmente fácil lidiar con parámetros de URL variables, etc.
Entonces digamos que tiene un parámetro
foo
que puede ser:En lugar de usar un montón de condicionales, puedes simplemente llamar
foo.to_boolean
y hará el resto de la magia por ti.En Rails, agrego esto a un inicializador nombrado
core_ext.rb
en casi todos mis proyectos ya que este patrón es muy común.fuente
"buy"=~/b/ => 0
Pero("buy"=~/b/).to_boolean => false
No pienses demasiado:
Entonces,
También puede agregar ".downcase", si le preocupan las letras mayúsculas.
fuente
nil.to_s == 'true' #false
fuente
value.to_s == 'true' ? true : false
if true then true, if false then false
¿Adivina qué? ¡Puedes eliminarlo por completo!value.to_s == 'true' ? true : false
debería servalue.to_s == 'true'
fuente
En una aplicación rails 5.1, utilizo esta extensión central construida sobre
ActiveRecord::Type::Boolean
. Funciona perfectamente para mí cuando deserializo un booleano de una cadena JSON.https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
inicializar extensiones centrales
rspec
fuente
En Rails prefiero usar
ActiveModel::Type::Boolean.new.cast(value)
como se menciona en otras respuestas aquíPero cuando escribo Ruby lib. luego uso un truco donde
JSON.parse
(biblioteca estándar de Ruby) convertirá la cadena "verdadero" entrue
y "falso" enfalse
. P.ej:Ejemplo de aplicación en vivo:
fuente
Trabajando en Rails 5
fuente
ActiveModel::Type::Boolean.new.cast("False") # => true
... Usar to_s.downcase en su entrada es una buena ideaTengo un pequeño truco para este.
JSON.parse('false')
volveráfalse
yJSON.parse('true')
volverá verdadero. Pero esto no funciona conJSON.parse(true || false)
. Entonces, si usa algo asíJSON.parse(your_value.to_s)
, debería lograr su objetivo de una manera simple pero hacky.fuente
Una joya como https://rubygems.org/gems/to_bool puede usar , pero se puede escribir fácilmente en una línea usando una expresión regular o un ternario.
ejemplo de expresiones regulares:
ejemplo ternario:
La ventaja del método regex es que las expresiones regulares son flexibles y pueden coincidir con una amplia variedad de patrones. Por ejemplo, si sospecha que var podría ser cualquiera de "True", "False", 'T', 'F', 't' o 'f', entonces puede modificar la expresión regular:
fuente
\A
/\z
es el comienzo / final de la cadena y^
/$
es el comienzo / final de la línea. Entonces sivar == "true\nwhatevs"
entoncesboolean == true
.var.eql?('true') ? true : false
mucho. ¡Gracias!Aunque me gusta el enfoque hash (lo he usado en el pasado para cosas similares), dado que solo te importa hacer coincidir los valores de verdad, ya que todo lo demás es falso, puedes verificar la inclusión en una matriz:
o si otros valores pudieran considerarse veraces:
tendrías que hacer otras cosas si tu original
value
pudiera ser un caso mixto:pero nuevamente, para su descripción específica de su problema, podría salirse con la suya con ese último ejemplo como solución.
fuente
En rieles, anteriormente hice algo como esto:
Lo cual es bueno si está tratando de hacer coincidir sus comparaciones de cadenas booleanas de la misma manera que lo harían los rieles para su base de datos.
fuente
Cerca de lo que ya está publicado, pero sin el parámetro redundante:
uso:
fuente