Come verificare se esistono parametri nei binari


179

Sto usando un'istruzione IF in Ruby on Rails per provare e verificare se sono impostati i parametri di richiesta. Indipendentemente dal fatto che siano impostati o meno entrambi i parametri, la prima parte di quanto segue se viene attivato il blocco. Come posso fare in modo che questa parte venga attivata SOLO se sono impostati sia params [: one] che params [: two]?

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

10
@Nakilon: dato che si paramstratta di un metodo controller Rails (che succede per restituire un HashWithIndifferentAccess), si tratta di Rails.
mu è troppo corto il

Risposte:


348

Tu vuoi has_key?:

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

Solo il controllo if(params[:one])verrà ingannato da un valore "lì ma zero" e "lì ma falso" e stai chiedendo l'esistenza. Potrebbe essere necessario differenziare:

  • Niente affatto.
  • Lì ma nil.
  • Lì ma false.
  • C'è solo una stringa vuota.

anche. Difficile a dirsi senza ulteriori dettagli sulla tua precisa situazione.


3
@sawa Non è possibile passare un nilparametro. Se il parametro esiste, sarà una stringa vuota.
Jacob Relkin,

5
@Jacob: non c'è alcuna garanzia che paramsnon sia stato pre-elaborato prima di arrivare a dove stiamo controllando cosa c'è dentro. Da qui la mia lista di possibili casi speciali da controllare. Meglio dire esattamente cosa intendi per IMHO.
mu è troppo corto il

1
@muistooshort my bad, that Python :(
FloatingRock

2
In Rails 5, l'oggetto params non è più un hash e non vedo il key?metodo. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson

1
@muistooshort Oh, bello. Sono ancora un po 'titubante nell'utilizzare metodi che non fanno parte dell'API documentata, ma sono sicuro che sia abbastanza sicuro. Sto chiamando params.to_h.key?per ora.
stephen.hanson,

86

Sono un fan di

params[:one].present?

Solo perché mantiene il params[sym]modulo, quindi è più facile da leggere.


1
Meglio, 3 caratteri più brevi, più semplici.
Bengala,

questa dovrebbe essere la migliore risposta valida!
jacktrade,

4
Attento usando presente? con booleani (metodo indefinito `present 'per true: TrueClass). La risposta accettata con has_key? funziona per tutti i tipi.
StCleezy,

2
Per essere chiari questo non funziona in alcuni casi come ad esempio false.present? => false Quindi non funzionerà quando, ad esempio, passa parametri tramite json body in quanto può passare booleani.
James,

1
se si utilizza questa logica in una vista, present non riuscirà poiché l'array di parametri è già invocato e non funzionerà se nulla. has_keyinvece ti dà quello che stai cercando.
Girolamo

22

usare il bianco? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

restituirà true se è vuoto o nullo

inoltre ... che non funzionerà se stai testando valori booleani .. da allora

>> false.blank?
=> true

in tal caso potresti usare

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

3
O present?che restituisce il contrario di blank?. Quindi potresti trasformarlo unlessin un ifse lo desideri.
Inkling

@Inkling che funziona, ma un inline unlessè ok. Ma sì, mi piace di più ifconpresent?
Orlando,

18

Puoi scriverlo in modo più succinto come il seguente:

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
Mi piace quanto sia pulito. Sono nuovo di Ruby però. Eventuali insidie ​​o casi limite persi che dovrei conoscere?
Sean,

10

Semplice come una torta:

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
Ciò non controlla se il parametro è presente ma è effettivamente impostato su zero.
Daemin,

@Daemin In realtà, tuttavia, un parametro non può essere impostato su zero in un'intestazione di richiesta. È zero o una stringa.
Jacob Relkin,

Sì, ma come hanno affermato altre persone, potrebbe essere modificato da qualcos'altro, da un plug-in, da una gemma o dal proprio codice, oppure non riesce ad analizzare per qualche bizzarro motivo.
Daemin,

4
Fare una torta è in realtà complicato
Cesar,

perché non usi a meno che
Alireza Rahmani Khalili il

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

5

Un modo molto semplice per fornire valori predefiniti ai tuoi parametri: params[:foo] ||= 'default value'


2
potresti fare params.fetch(:foo, 'default value')anche tu
Mario Pérez, il

5

Ho appena letto questo sulle lezioni di RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

Puoi usare blank? metodo equivalente aparams[:one].nil? || params[:one].empty?

(per esempio)

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

Perfetto, stavo usandoparams[:one].nil? || params[:one].empty?
GOXR3PLUS l'

ha chiave è il metodo giusto, il tuo metodo ha presupposto che questo parametro esista già, quindi stai convalidando zero su zero che potrebbe funzionare ma non il metodo migliore.
Paul Brunache,

3

Puoi anche fare quanto segue:

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

Tendo a utilizzare la soluzione di cui sopra quando voglio controllare più di uno o due parametri.

.values_at restituisce e array con zero al posto di qualsiasi chiave param non definita. vale a dire:

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

restituirà quanto segue:

[3,nil,5] 

.includes? (zero) quindi controlla l'array per eventuali valori nulli. Restituirà vero se l'array include zero.

In alcuni casi potresti anche voler verificare che i parametri non contengano e svuotino la stringa con un valore falso.

È possibile gestire tali valori aggiungendo il seguente codice sopra l'istruzione

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

tutti insieme sembrerebbe così:

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

È importante notare che delete_if modificherà il tuo hash / params, quindi usa con cautela.

La soluzione sopra richiede chiaramente un po 'più di lavoro per la configurazione, ma ne vale la pena se stai controllando più di uno o due parametri.


3

Oltre alle risposte precedenti: has_key?e has_value?hanno alternative più brevi in forma di key?e value?. Il team di Ruby suggerisce anche di utilizzare alternative più brevi, ma per leggibilità alcuni potrebbero ancora preferire versioni più lunghe di questi metodi.

Quindi nel tuo caso sarebbe qualcosa di simile

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

NB! .key?controllerà solo se esiste la chiave e ignora il valore possibile. Ad esempio:

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

Ecco cosa faccio

before_action :validate_presence

e quindi i seguenti metodi:

    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

Ho appena messo insieme questo per lo stesso problema:

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 prima riga controlla se le nostre chiavi target sono presenti nelle chiavi dei parametri usando il sottoinsieme <=? operatore. Enumerable.all? senza blocco per impostazione predefinita restituisce false se un valore è zero o falso.


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

Puoi anche verificare se i parametri sono vuoti usando params [: two] .empty


1
Mentre questo copre il caso in cui entrambi i parametri sono definiti. Non copre il caso in cui uno di essi giudichi falso.
EmFi

0

Provo una risposta in ritardo, ma da lontano vista:

Se vuoi sapere se sono impostati i valori in un (qualsiasi) hash, tutto quanto sopra risponde a true, a seconda del loro punto di vista.

Se vuoi testare i tuoi parametri (GET / POST ..), dovresti usare qualcosa di più speciale per quello che ti aspetti sia il valore params[:one], qualcosa come

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

ignorando il parametro (GET / POST) come se non fossero impostati, se non si adattano come previsto

solo un if params[:one] rilevamento con o senza zero / true è un passaggio per aprire la tua pagina per l'hacking, perché, in genere, è il passaggio successivo per utilizzare qualcosa di simile select ... where params[:one] ..., se questo è previsto o meno, attivo o all'interno o dopo un framework.

una risposta o solo un suggerimento

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.