Comment tester si des paramètres existent dans les rails


179

J'utilise une instruction IF dans Ruby on Rails pour essayer de tester si les paramètres de demande sont définis. Indépendamment du fait que les deux paramètres sont définis ou non, la première partie de ce qui suit si le bloc est déclenchée. Comment puis-je faire déclencher cette partie UNIQUEMENT si les paramètres [: one] et params [: two] sont définis?

if (defined? params[:one]) && (defined? params[:two])
 ... do something ...
elsif (defined? params[:one])
 ... do something ...
end

10
@Nakilon: Étant donné qu'il paramss'agit d'une méthode de contrôleur Rails (qui retourne un HashWithIndifferentAccess), il s'agit de Rails.
mu est trop court

Réponses:


348

Vous voulez has_key?:

if(params.has_key?(:one) && params.has_key?(:two))

La simple vérification if(params[:one])sera trompée par une valeur «là mais nul» et «là mais faux» et vous posez des questions sur l'existence. Vous devrez peut-être différencier:

  • Pas du tout.
  • Là mais nil.
  • Là mais false.
  • Là mais une chaîne vide.

ainsi que. Difficile à dire sans plus de détails sur votre situation précise.


3
@sawa Il n'est pas possible de passer un nilparamètre. Si le paramètre existe, ce sera une chaîne vide.
Jacob Relkin

5
@Jacob: Il n'y a aucune garantie qui paramsn'ait pas été prétraité avant d'arriver à l'endroit où nous vérifions ce qu'il contient. D'où ma liste de cas particuliers possibles à vérifier. Mieux vaut dire exactement ce que vous voulez dire à mon humble avis.
mu est trop court le

1
@muistooshort mon mauvais, c'était Python :(
FloatingRock

2
Dans Rails 5, l'objet params n'est plus un hachage, et je ne vois pas la key?méthode. edgeapi.rubyonrails.org/classes/ActionController/...
stephen.hanson

1
@muistooshort Oh, c'est bien. J'hésite encore un peu à utiliser des méthodes qui ne font pas partie de l'API documentée, mais je suis sûr que c'est assez sûr. J'appelle params.to_h.key?depuis maintenant.
stephen.hanson

86

Je suis un fan de

params[:one].present?

Simplement parce qu'il conserve le params[sym]formulaire pour qu'il soit plus facile à lire.


1
Mieux, 3 caractères plus courts, plus simple.
Bengala

celui-ci devrait être la meilleure réponse valable!
jacktrade

4
Attention à utiliser le présent? avec des booléens (méthode non définie `present 'pour true: TrueClass). La réponse acceptée avec has_key? fonctionne pour tous les types.
StCleezy

2
Pour être clair, cela ne fonctionne pas dans certains cas, par exemple false.present? => false Donc, cela ne fonctionnera pas lorsque, par exemple, le passage de paramètres via le corps json peut transmettre des booléens.
James du

1
si vous utilisez cette logique dans une vue, present échouera car le tableau de paramètres est déjà appelé et échouera s'il est nul. has_keyvous donne plutôt ce que vous recherchez.
Jerome

22

utiliser du blanc? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

unless params[:one].blank? && params[:two].blank?

retournera vrai si c'est vide ou nul

aussi ... cela ne fonctionnera pas si vous testez des valeurs booléennes .. puisque

>> false.blank?
=> true

dans ce cas, vous pouvez utiliser

unless params[:one].to_s.blank? && params[:two].to_s.blank?

3
Ou present?qui renvoie le contraire de blank?. Vous pouvez donc unlessen faire un ifsi vous le souhaitez.
Inkling

@Inkling ça marche, mais un inline unlessça va. Mais ouais, j'aime mieux ifavecpresent?
Orlando

18

Vous pouvez l'écrire plus succinctement comme suit:

required = [:one, :two, :three]
if required.all? {|k| params.has_key? k}
  # here you know params has all the keys defined in required array
else
  ...
end

1
J'aime à quel point c'est propre. Je suis cependant nouveau sur Ruby. Y a-t-il des pièges ou des cas de pointe manqués que je devrais connaître?
Sean

10

Simple comme bonjour:

if !params[:one].nil? and !params[:two].nil?
  #do something...
elsif !params[:one].nil?
  #do something else...
elsif !params[:two].nil?
  #do something extraordinary...
end

3
Cela ne vérifie pas si le paramètre est là mais est en fait défini sur nil.
Daemin

@Daemin En réalité, cependant, un paramètre ne peut pas être défini sur nil dans un en-tête de requête. C'est soit nul, soit une chaîne.
Jacob Relkin

Oui, mais comme d'autres personnes l'ont déclaré, il peut être modifié par quelque chose d'autre, un plugin, une gemme ou votre propre code, ou tout simplement échouer à l'analyse pour une raison étrange.
Daemin

4
Faire une tarte est en fait compliqué
Cesar

pourquoi vous ne l'utilisez pas à moins
Alireza Rahmani Khalili

5
if params[:one] && params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end

5

Un moyen très simple de fournir des valeurs par défaut à vos paramètres: params[:foo] ||= 'default value'


2
vous pourriez faire params.fetch(:foo, 'default value')aussi
Mario Pérez

5

Je viens de lire ceci sur les classes RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

vous pouvez utiliser une blank?méthode équivalente àparams[:one].nil? || params[:one].empty?

(par exemple)

if params[:one].blank? 
  # do something if not exist
else
  # do something if exist
end

Parfait, params[:one].nil? || params[:one].empty?
j'utilisais

has key est la bonne méthode, votre méthode suppose que ce paramètre existe déjà, donc vous validez nil sur nil ce qui pourrait fonctionner mais pas la meilleure méthode.
Paul Brunache

3

Vous pouvez également effectuer les opérations suivantes:

unless params.values_at(:one, :two, :three, :four).includes?(nil)
 ... excute code ..
end 

J'ai tendance à utiliser la solution ci-dessus lorsque je veux vérifier plus d'un ou deux paramètres.

.values_at renvoie un tableau avec nil à la place de toute clé de paramètre non définie. c'est à dire:

some_hash = {x:3, y:5}
some_hash.values_at(:x, :random, :y}

renverra ce qui suit:

[3,nil,5] 

.includes? (nil) vérifie alors le tableau pour toutes les valeurs nil. Il retournera true si le tableau inclut nil.

Dans certains cas, vous pouvez également vérifier que les paramètres ne contiennent pas de chaîne vide sur une valeur fausse.

Vous pouvez gérer ces valeurs en ajoutant le code suivant au-dessus de l'instruction sauf.

params.delete_if{|key,value| value.blank?}

tous ensemble, cela ressemblerait à ceci:

 params.delete_if{|key,value| value.blank?}
 unless params.values_at(:one, :two, :three, :four).includes?(nil)
   ... excute code ..
  end

Il est important de noter que delete_if modifiera votre hachage / paramètres, utilisez donc avec prudence.

La solution ci-dessus demande clairement un peu plus de travail à mettre en place, mais en vaut la peine si vous vérifiez plus d'un ou deux paramètres.


3

En plus des réponses précédentes: has_key?et has_value?ont des alternatives plus courtes sous forme de key?et value?. L'équipe Ruby suggère également d' utiliser des alternatives plus courtes, mais pour plus de lisibilité certains pourraient encore préférer des versions plus longues de ces méthodes.

Par conséquent, dans votre cas, ce serait quelque chose comme

if params.key?(:one) && params.key?(:two)
  ... do something ...
elsif params.key?(:one)
  ... do something ...
end

NB! .key?vérifiera simplement si la clé existe et ignore la valeur possible. Par exemple:

2.3.3 :016 > a = {first: 1, second: nil, third: ''}
  => {:first=>1, :second=>nil, :third=>""}
2.3.3 :017 > puts "#{a.key?(:first)}, #{a.key?(:second)}, #{a.key?(:third), #{a.key?(:fourth)}}"
true, true, true, false

2

Voilà ce que je fais

before_action :validate_presence

puis les méthodes suivantes:

    def check_presence
  params[:param1].present? && params[:param2].present?
 end

 def validate_presence
  if !check_presence
    render json:  {
                      error:  {
                                message: "Bad Request, parameters missing.",
                                status: 500
                              }
                    }
  end
 end

1

Juste reconstitué ceci pour le même problème:

before_filter :validate_params

private

def validate_params
  return head :bad_request unless params_present?
end

def params_present?  
  Set.new(%w(one two three)) <= (Set.new(params.keys)) &&
  params.values.all?
end

la première ligne vérifie si nos clés cibles sont présentes dans les clés des paramètres en utilisant le sous-ensemble <=? opérateur. Enumerable.all? sans bloc par défaut renvoie false si une valeur est nulle ou fausse.


0
if params[:one] && param[:two]
  ... excute code ..
end

Vous pouvez également vérifier si les paramètres sont vides en utilisant params [: two] .empty


1
Bien que cela couvre le cas où les deux paramètres sont définis. Il ne couvre pas le cas où l'un d'eux évalue faux.
EmFi

0

J'essaye une réponse tardive, mais de loin:

Si vous voulez savoir si les valeurs d'un hachage (quelconque) sont définies, tout ce qui précède répond à un vrai, en fonction de leur point de vue.

Si vous voulez tester vos paramètres (GET / POST ..), vous devez utiliser quelque chose de plus spécial que ce que vous attendez d'être la valeur params[:one], quelque chose comme

if params[:one]~=/   / and  params[:two]~=/[a-z]xy/

ignorer le paramètre (GET / POST) comme s'ils n'étaient pas définis, s'ils ne correspondent pas comme prévu

juste une if params[:one] détection avec ou sans nil / true est une étape pour ouvrir votre page pour le piratage, car c'est généralement la prochaine étape d'utiliser quelque chose commeselect ... where params[:one] ... , si cela est prévu ou non, actif ou dans ou après un cadre.

une réponse ou juste un indice

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.