Eu tenho um valor que será uma de quatro coisas: boolean true, boolean false, a string "true" ou a string "false". Desejo converter a string em booleano se for uma string, caso contrário, não a modificarei. Em outras palavras:
"verdadeiro" deve se tornar verdadeiro
"falso" deve se tornar falso
verdadeiro deve permanecer verdadeiro
falso deveria permanecer falso
ruby
string
boolean
type-conversion
esmeril
fonte
fonte
true
oufalse
ou é suficiente se o resultado for verdadeiro ou falso? Se for o último, entãofalse
já é falsey, e ambostrue
e'true'
são verdadeiros, então o único valor para o qual o resultado ainda não está correto é'false'
:if input == 'false' then true else input end
deveria fazê-lo.!!(if input == 'false' then true else input end)
. O segundo!
converte o valor de retorno em um booleano que é o oposto do que você deseja; o primeiro!
então faz a correção. Esse "truque" já existe há muito tempo. Nem todo mundo gosta disso.Respostas:
fonte
obj.to_s.downcase == 'true'
downcase!
e você alocará 1 objeto a menos.downcase
irá duplicar a string existente. Quando Frozen String Literals se tornar uma opção padrão do Ruby, isso terá menos importância.Se você usa Rails 5, você pode fazer
ActiveModel::Type::Boolean.new.cast(value)
.No Rails 4.2, use
ActiveRecord::Type::Boolean.new.type_cast_from_user(value)
.O comportamento é um pouco diferente, como no Rails 4.2, o valor verdadeiro e falso são verificados. No Rails 5, apenas valores falsos são verificados - a menos que os valores sejam nulos ou correspondam a um valor falso, ele é considerado verdadeiro. Os valores falsos são iguais nas duas versões:
FALSE_VALUES = [false, 0, "0", "f", "F", "false", "FALSE", "off", "OFF"]
Fonte do Rails 5: https://github.com/rails/rails/blob/5-1-stable/activemodel/lib/active_model/type/boolean.rb
fonte
FALSE_VALUES
em Rails também inclua "não".ActiveRecord::Type::Boolean::FALSE_VALUES << "no"
a um inicializador.ActiveModel::Type::Boolean.new.cast(value)
diferencia maiúsculas de minúsculas ... então 'False' será avaliado como verdadeiro, assim como qualquer outra string, exceto 'false'. strings vazias''
padrão para nil, não false. ^^ informações valiosas fornecidas aqui por @thomasfedb sobre a personalização do inicializadorActiveModel::Type::Boolean.new.cast(nil)
também retornanil
.ActiveRecord::Type::Boolean::FALSE_VALUES
está congelado.Eu frequentemente usei esse padrão para estender o comportamento central do Ruby para tornar mais fácil lidar com a conversão de tipos de dados arbitrários em valores booleanos, o que torna realmente fácil lidar com parâmetros variáveis de URL, etc.
Então, digamos que você tenha um parâmetro
foo
que pode ser:Em vez de usar um monte de condicionais, você pode apenas chamar
foo.to_boolean
e ele fará o resto da mágica para você.No Rails, eu adiciono isso a um inicializador chamado
core_ext.rb
em quase todos os meus projetos, já que esse padrão é muito comum.fonte
"buy"=~/b/ => 0
Mas("buy"=~/b/).to_boolean => false
Não pense muito:
Assim,
Você também pode adicionar ".downcase", se estiver preocupado com letras maiúsculas.
fonte
nil.to_s == 'true' #false
fonte
value.to_s == 'true' ? true : false
if true then true, if false then false
Adivinha o quê? Você pode removê-lo completamente!value.to_s == 'true' ? true : false
deveria servalue.to_s == 'true'
fonte
Em um aplicativo Rails 5.1, eu uso esta extensão principal construída sobre ele
ActiveRecord::Type::Boolean
. Está funcionando perfeitamente para mim quando eu desserializo booleano da string JSON.https://api.rubyonrails.org/classes/ActiveModel/Type/Boolean.html
inicializar extensões principais
rspec
fonte
Em Rails eu prefiro usar
ActiveModel::Type::Boolean.new.cast(value)
como mencionado em outras respostas aquiMas quando escrevo Ruby lib simples. então eu uso um hack onde
JSON.parse
(biblioteca Ruby padrão) irá converter string "true" paratrue
e "false" parafalse
. Por exemplo:Exemplo de aplicativo ao vivo:
fonte
Trabalhando no Rails 5
fonte
ActiveModel::Type::Boolean.new.cast("False") # => true
... Usar to_s.downcase em sua entrada é uma boa ideiaEu tenho um pequeno hack para este.
JSON.parse('false')
retornaráfalse
eJSON.parse('true')
retornará verdadeiro. Mas isso não funciona comJSON.parse(true || false)
. Portanto, se você usar algo parecidoJSON.parse(your_value.to_s)
, deverá atingir seu objetivo de uma forma simples, mas "hacky".fonte
Uma gema como https://rubygems.org/gems/to_bool pode ser usada, mas pode ser facilmente escrita em uma linha usando um regex ou ternário.
exemplo regex:
exemplo ternário:
A vantagem do método regex é que as expressões regulares são flexíveis e podem corresponder a uma ampla variedade de padrões. Por exemplo, se você suspeitar que var pode ser "Verdadeiro", "Falso", 'T', 'F', 't' ou 'f', poderá modificar o regex:
fonte
\A
/\z
é o início / fim da string e^
/$
é o início / fim da linha. Então, sevar == "true\nwhatevs"
entãoboolean == true
.var.eql?('true') ? true : false
muito. Obrigado!Embora eu goste da abordagem de hash (já usei no passado para coisas semelhantes), dado que você realmente só se preocupa em combinar valores verdadeiros - já que - tudo o mais é falso - você pode verificar a inclusão em uma matriz:
ou se outros valores podem ser considerados verdadeiros:
você teria que fazer outras coisas se o original
value
fosse maiúsculo:mas, novamente, para sua descrição específica de seu problema, você poderia usar esse último exemplo como sua solução.
fonte
Em trilhos, já fiz algo assim:
O que é bom se você está tentando combinar suas comparações de strings booleanas da mesma maneira que o rails faria para seu banco de dados.
fonte
Perto do que já foi postado, mas sem o parâmetro redundante:
uso:
fonte