Comment soumettre un paramètre booléen dans Rails?

Je soumets un paramètre show_all avec la valeur true . Cette valeur n’est pas associée à un modèle.

Mon contrôleur atsortingbue ce paramètre à une variable d’instance:

 @show_all = params[:show_all] 

Cependant, @show_all.is_a? Ssortingng @show_all.is_a? Ssortingng , et if @show_all == true échoue toujours.

Quelles sont les valeurs analysées par Rails en tant que booléens? Comment puis-je spécifier explicitement que mon paramètre est un booléen et non une chaîne?

Je voulais commenter la réponse zetetic mais comme je ne peux pas le faire, je posterai cela comme une réponse.

Si tu utilises

@show_all = params[:show_all] == "1"

alors vous pouvez laisser tomber ? true : false ? true : false car params[:show_all] == "1" instruction params[:show_all] == "1" elle-même évaluera à true ou false et donc l’opérateur ternaire n’est pas nécessaire.

MISE À JOUR: Rails 5:

 ActiveRecord::Type::Boolean.new.deserialize('0') 

UPDATE: Rails 4.2 a une API publique pour ceci:

 ActiveRecord::Type::Boolean.new.type_cast_from_user("0") # false 

RÉPONSE PRÉCÉDENTE:

ActiveRecord maintient une liste de représentations pour true / false dans https://github.com/rails/rails/blob/master/activerecord/lib/active_record/connection_adapters/column.rb

 2.0.0-p247 :005 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("ON") 2.0.0-p247 :006 > ActiveRecord::ConnectionAdapters::Column.value_to_boolean("F") 

Cela ne fait pas partie de l’API publique de Rails, donc je l’ai intégré dans une méthode d’assistance:

 class ApplicationController < ActionController::Base private def parse_boolean(value) ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value) end end 

et ajouté un test de base:

 class ApplicationControllerTest < ActionController::TestCase test "parses boolean params" do refute ApplicationController.new.send(:parse_boolean, "OFF") assert ApplicationController.new.send(:parse_boolean, "T") end end 

Cette question est assez ancienne, mais depuis que je suis tombé sur cette question à quelques resockets et que je n’aimais aucune des solutions proposées, j’ai moi-même piraté quelque chose, ce qui permet d’utiliser plusieurs chaînes comme ‘yes’, ‘on’ , ‘t’ et le contraire pour faux.

Monkey corrige la classe Ssortingng et ajoute une méthode pour les convertir en booléen et place ce fichier dans /config/initializers comme suggéré ici: Monkey Patching in Rails 3

 class Ssortingng def to_bool return true if ['true', '1', 'yes', 'on', 't'].include? self return false if ['false', '0', 'no', 'off', 'f'].include? self return nil end end 

Notez que si la valeur n’est aucun des valides pour true ou false, alors elle renvoie nil. Ce n’est pas la même chose que de rechercher ?paid=false (retourner tous les enregistrements non payés) que ?paid= (je ne spécifie pas si le paiement doit être effectué ou non – alors défaussez-le).

Ensuite, suivant cet exemple, la logique de votre contrôleur ressemblerait à ceci:

 Something.where(:paid => params[:paid].to_bool) unless params[:paid].try(:to_bool).nil? 

C’est plutôt chouette et aide à garder les contrôleurs / modèles propres.

 @show_all = params[:show_all] == "1" ? true : false 

Cela devrait fonctionner correctement si vous transmettez la valeur depuis une case à cocher – une clé manquante dans un hachage génère un zéro, ce qui équivaut à false dans un conditionnel.

MODIFIER

Comme indiqué ici , l’opérateur ternaire n’est pas nécessaire, il peut donc simplement être:

@show_all = params[:show_all] == "1"

Vous pouvez modifier votre déclaration d’égalité pour:

 @show_all == "true" 

Si vous voulez que ce soit un booléen, vous pouvez créer une méthode sur la classe de chaîne pour convertir une chaîne en booléen.

Je pense que la solution la plus simple consiste à tester les parameters “booléens” par rapport à leur représentation sous forme de chaîne.

 @show_all = params[:show_all] if @show_all.to_s == "true" # do stuff end 

Indépendamment du fait que Rails fournisse le paramètre en tant que chaîne “true” ou “false” ou en tant que TrueClass ou FalseClass, ce test fonctionnera toujours.

Vous pouvez convertir tous vos parameters booléens en vrais booléens comme ceci:

 %w(show_all, show_featured).each do |bool_param| params[bool_param.to_sym] = params[bool_param.to_sym] == "true" end 

Dans cette solution, aucun paramètre ne deviendrait faux.

Une autre approche consiste à ne transmettre que la clé sans valeur. Bien que l’utilisation d’ ActiveRecord::Type::Boolean.new.type_cast_from_user(value) soit plutôt ActiveRecord::Type::Boolean.new.type_cast_from_user(value) , il peut arriver que l’affectation d’une valeur à la clé param soit redondante.

Considérez ce qui suit: Dans la vue d’index de mes produits par défaut, je souhaite afficher uniquement la collection de produits délimitée (par exemple, ceux qui sont dans le stock). Si je veux retourner tous les produits, je peux envoyer myapp.com/products?show_all=true et typecast le paramètre show_all pour une valeur booléenne.

Cependant, l’option opposée – myapp.com/products?show_all=false n’a pas de sens car elle renverra la même collection de produits que myapp.com/products .

Une alternative:

si je veux retourner la collection entière non découpée, alors j’envoie myapp.com/products?all et dans mon controller

 private def show_all? params.key?(:all) end 

Si la clé est présente dans les parameters, alors, quelle que soit sa valeur, je saurai que je dois retourner tous les produits, pas besoin de transgresser la valeur.

Vous pouvez append les éléments suivants à votre modèle:

 def show_all= value @show_all = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value) end