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.
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
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