J'ai une application Rails et j'utilise jQuery pour interroger ma vue de recherche en arrière-plan. Il existe des champs q
(terme de recherche) start_date
, end_date
et internal
. Le internal
champ est une case à cocher et j'utilise la is(:checked)
méthode pour créer l'url qui est 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 params[:internal]
parce qu'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 ceci:
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 manière plus rubis de traiter ce problème! N'y a-t-il pas ...?
ActiveRecord fournit une manière propre de faire ceci.
def is_true?(string) ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include?(string) end
ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
a toutes les représentations évidentes des valeurs True sous forme de chaînes.la source
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)
(source) apidock.com/rails/v3.0.9/ActiveRecord/ConnectionAdapters/ColumnActiveRecord::Type::Boolean.new.type_cast_from_user("true")
=> trueActiveRecord::Type::Boolean.new.type_cast_from_user("T")
=> trueActiveModel::Type::Boolean
semble être un chemin beaucoup plus approprié - bien queActiveRecord::ConnectionAdapters::Column::TRUE_VALUES
contenant des valeurs de «vérité», on pourrait soutenir que ce n'est qu'incidemment le cas, et que des valeurs qui devraient être considérées comme véridiques pour ce cas d'utilisation spécifique mais pas pour d'autres pourraient être incluses. D'autre part,ActiveModel::Type::Boolean
est apparemment conçu pour être utilisé de manière générique.Avis de sécurité
Notez que cette réponse sous sa forme simple n'est appropriée que pour l'autre cas d'utilisation répertorié ci-dessous plutôt que pour celui de la question. Bien que pour la plupart corrigées, de nombreuses vulnérabilités de sécurité liées à YAML ont été causées par le chargement de l'entrée utilisateur en tant que YAML.
Une astuce que j'utilise pour convertir des chaînes en booléens est
YAML.load
, par exemple:YAML.load(var) # -> true/false if it's one of the below
YAML bool accepte beaucoup de chaînes véridiques / fausses:
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 morceau de code de configuration comme celui-ci:
config.etc.something = ENV['ETC_SOMETHING']
Et en ligne de commande:
$ export ETC_SOMETHING=false
Maintenant, puisque les
ENV
vars sont des chaînes une fois dans le code,config.etc.something
la valeur de s serait la chaîne"false"
et elle serait incorrectement évaluéetrue
. Mais si vous aimez ça:config.etc.something = YAML.load(ENV['ETC_SOMETHING'])
tout irait bien. Ceci est également compatible avec le chargement de configurations à partir de fichiers .yml.
la source
Il n'y a aucun moyen intégré de 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 également, c'est d'utiliser 0 et non-0 au lieu de littéraux faux / vrai:
def to_boolean(s) !s.to_i.zero? end
la source
.match
c'est un peu plus facile à lire.ActiveRecord::Type::Boolean.new.type_cast_from_user
fait cela selon les mappages internes de RailsConnectionAdapters::Column::TRUE_VALUES
etConnectionAdapters::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 <main> 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 <main> at (pry):8) => false
Vous pouvez donc créer votre propre méthode
to_b
(outo_bool
outo_boolean
) dans un initialiseur comme celui-ci:class String def to_b ActiveRecord::Type::Boolean.new.type_cast_from_user(self) end end
la source
Vous pouvez utiliser wannabe_bool gem. https://github.com/prodis/wannabe_bool
Ce gem implémente une
#to_b
méthode pour les classes String, Integer, Symbol et NilClass.params[:internal].to_b
la source
Dans Rails 5, vous pouvez utiliser
ActiveRecord::Type::Boolean.new.cast(value)
pour le convertir en booléen.la source
Je ne pense pas que quelque chose comme ça soit intégré à Ruby. Vous pouvez rouvrir la classe String et y ajouter la méthode to_bool:
class String 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
la source
to_bool
retour de fonctionnil
; cela semble faux. Les autres fonctions de conversion ne font pas cela:"a".to_i
renvoie0
, pasnil
Peut-être
str.to_s.downcase == 'true'
par souci d'exhaustivité. Alors rien ne peut planter même sistr
nul ou 0.la source
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
la source
Vous pouvez envisager d'ajouter
internal
à votre URL uniquement si c'est vrai, alors si la case n'est pas cochée et que vous ne l'ajoutez pas, ceparams[:internal]
seraitnil
, ce qui donne la valeur false dans Ruby.Je ne suis pas très familier avec le jQuery spécifique que vous utilisez, mais existe-t-il un moyen plus propre d'appeler ce que vous voulez que de créer manuellement une chaîne d'URL? Avez-vous jeté un œil à
$get
et$ajax
?la source
Vous pouvez ajouter à la classe String pour avoir la méthode to_boolean. Ensuite, vous pouvez faire 'true'.to_boolean ou' 1'.to_boolean
class String def to_boolean self == 'true' || self == '1' end end
la source
Je suis surpris que personne n'ait publié cette solution simple. C'est si vos chaînes vont être "true" ou "false".
def to_boolean(str) eval(str) end
la source
to_boolean("ActiveRecord::Base.connection.execute('DROP TABLE *')")
, cela détruira votre base de données (et retournera vrai!). Amusez-vous bien: Dbool = nil; bool = eval(str) if ["true", "false"].include?(str)
Je pensais juste que je devrais ajouter pour des clarifications.