Chaîne “true” et “false” à booléen

J’ai une application Rails et j’utilise jQuery pour interroger la vue de recherche en arrière-plan. Il existe des champs q (terme de recherche), start_date , end_date et internal . Le champ internal est une case à cocher et j’utilise la méthode is(:checked) pour générer l’url interrogée:

 $.getScript(document.URL + "?q=" + $("#search_q").val() + "&start_date=" + $("#search_start_date").val() + "&end_date=" + $("#search_end_date").val() + "&internal=" + $("#search_internal").is(':checked')); 

Maintenant, mon problème est dans params[:internal] car il y a une chaîne contenant “true” ou “false” et je dois la convertir en booléen. Bien sûr je peux le faire comme ça:

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

Mais je pense qu’il doit y avoir une façon plus Rubisienne de traiter ce problème! N’est-ce pas …?

Pour autant que je sache, il n’y a pas de méthode intégrée permettant de convertir des chaînes en booléens, mais si vos chaînes ne contiennent que 'true' et 'false' vous pouvez raccourcir votre méthode de la manière suivante:

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

ActiveRecord fournit une manière propre de le faire.

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

ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES a toutes les représentations évidentes des valeurs True en tant que chaînes.

Avis de sécurité

Notez que cette réponse sous sa forme nue ne convient que pour les autres cas d’utilisation listés ci-dessous plutôt que pour la question. Bien que la plupart des problèmes aient été résolus, de nombreuses vulnérabilités de sécurité liées à YAML ont été causées par le chargement d’une entrée utilisateur en tant que YAML.


Un truc que j’utilise pour convertir des chaînes en bools est YAML.load , par exemple:

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

YAML bool accepte pas mal de cordes de vérités:

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

Un autre cas d’utilisation

Supposons que vous ayez un code de configuration comme celui-ci:

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

Et en ligne de commande:

 $ export ETC_SOMETHING=false 

Maintenant que les vars ENV sont des chaînes une fois dans le code, la valeur de config.etc.something serait la chaîne "false" et sa valeur serait incorrecte. Mais si vous faites comme ça:

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

tout irait bien. Ceci est également compatible avec le chargement de configs à partir de fichiers .yml.

Il n’y a pas de moyen intégré pour gérer cela (bien que l’actionpack puisse avoir une aide pour cela). Je conseillerais quelque chose comme ça

 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 

Ce qui fonctionne aussi bien, c’est d’utiliser 0 et non-0 au lieu de littéraux faux / vrais:

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

ActiveRecord::Type::Boolean.new.type_cast_from_user fait conformément aux mappages internes de Rails ConnectionAdapters::Column::TRUE_VALUES et 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 
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
at (pry):8) => false

Vous pouvez donc créer votre propre to_b (ou to_bool ou to_boolean ) dans un initialiseur comme ceci:

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

Vous pouvez utiliser gem wannabe_bool. https://github.com/prodis/wannabe_bool

Ce bijou implémente une méthode #to_b pour les classes Ssortingng, Integer, Symbol et NilClass.

 params[:internal].to_b 

Dans Rails 5, vous pouvez utiliser ActiveRecord::Type::Boolean.new.cast(value) pour le ActiveRecord::Type::Boolean.new.cast(value) booléen.

Je ne pense pas que quelque chose comme ça soit intégré dans Ruby. Vous pouvez rouvrir la classe Ssortingng et y append la méthode to_bool:

 class Ssortingng def to_bool return true if self=="true" return false if self=="false" return nil end end 

Ensuite, vous pouvez l’utiliser n’importe où dans votre projet, comme ceci: params[:internal].to_bool

En regardant le code source de Virtus , je ferais peut-être quelque chose comme ceci:

 def to_boolean(s) map = Hash[%w[true yes 1].product([true]) + %w[false no 0].product([false])] map[s.to_s.downcase] end 

Peut-être que str.to_s.downcase == 'true' pour être complet. Alors rien ne peut planter même si str est nul ou 0.

Vous pourriez envisager d’append uniquement internal à votre URL si elle est vraie, alors si la case à cocher n’est pas cochée et que vous ne l’ajoutez pas, params[:internal] serait nil , ce qui équivaut à false dans Ruby.

Je ne connais pas bien jQuery, mais y a-t-il un moyen plus simple d’appeler ce que vous voulez que de créer manuellement une chaîne d’URL? Avez-vous regardé $get et $ajax ?

Vous pouvez append à la classe Ssortingng pour avoir la méthode de to_boolean. Ensuite, vous pouvez faire ‘true’.to_boolean ou’ 1′.to_boolean

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

Je suis surpris que personne n’ait posté cette solution simple. C’est à dire si vos chaînes vont être “vraies” ou “fausses”.

 def to_boolean(str) eval(str) end