So testen Sie, ob Parameter in Schienen vorhanden sind


179

Ich verwende eine IF-Anweisung in Ruby on Rails, um zu testen, ob Anforderungsparameter festgelegt sind. Unabhängig davon, ob beide Parameter eingestellt sind oder nicht, wird der erste Teil des folgenden Blocks ausgelöst. Wie kann ich diesen Teil NUR auslösen lassen, wenn sowohl params [: one] als auch params [: two] gesetzt sind?

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

10
@Nakilon: Da es sich paramsum eine Rails-Controller-Methode handelt (die zufällig einen HashWithIndifferentAccess zurückgibt), handelt es sich um Rails.
Mu ist zu kurz

Antworten:


344

Sie wollen has_key?:

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

Nur das Überprüfen if(params[:one])wird durch einen "da aber null" und "da aber falsch" Wert getäuscht und Sie fragen nach der Existenz. Möglicherweise müssen Sie unterscheiden:

  • Überhaupt nicht da.
  • Da aber nil.
  • Da aber false.
  • Da aber eine leere Schnur.

auch. Schwer zu sagen ohne weitere Details Ihrer genauen Situation.


3
@sawa Es ist nicht möglich, einen nilParameter zu übergeben. Wenn der Parameter vorhanden ist, handelt es sich um eine leere Zeichenfolge.
Jacob Relkin

5
@Jacob: Es gibt keine Garantie, paramsdie nicht vorverarbeitet wurde, bevor wir dort ankommen , wo wir überprüfen, was darin enthalten ist. Daher meine Liste möglicher Sonderfälle zu überprüfen. Am besten genau sagen, was du meinst IMHO.
Mu ist zu kurz

1
@ Muistooshort mein schlechtes, das war Python :(
FloatingRock

2
In Rails 5 ist das params-Objekt kein Hash mehr, und ich sehe die key?Methode nicht. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson

1
@ Muistooshort Oh, schön. Ich zögere immer noch ein wenig, Methoden zu verwenden, die nicht Teil der dokumentierten API sind, aber ich bin sicher, dass dies sicher genug ist. Ich habe params.to_h.key?jetzt angerufen .
stephen.hanson

85

Ich bin ein Fan von

params[:one].present?

Nur weil das params[sym]Formular so bleibt , dass es leichter zu lesen ist.


1
Besser, 3 Zeichen kürzer, einfacher.
Bengala

Dies sollte die beste gültige Antwort sein!
Jacktrade

4
Vorsichtig mit Geschenk umgehen? mit Booleschen Werten (undefinierte Methode `present 'für true: TrueClass). Die akzeptierte Antwort mit has_key? funktioniert für alle Typen.
StCleezy

2
Um klar zu sein, funktioniert dies in einigen Fällen nicht als zB false.present? => false Funktioniert also nicht, wenn z. B. Parameter über json body übergeben werden, da Boolesche Werte übergeben werden können.
James

Wenn Sie diese Logik in einer Ansicht verwenden, schlägt present fehl, da das Parameterarray bereits aufgerufen wird, und schlägt fehl, wenn nil. has_keygibt Ihnen stattdessen, was Sie suchen.
Jerome

22

leer verwenden? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

wird true zurückgeben, wenn es leer oder null ist

auch ... das wird nicht funktionieren, wenn Sie boolesche Werte testen .. da

>> false.blank?
=> true

in diesem Fall könnten Sie verwenden

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

3
Oder present?was das Gegenteil von zurückgibt blank?. Sie könnten das also unlessin ein verwandeln, ifwenn Sie wollten.
Inkling

@Inkling das funktioniert, aber eine Inline ist unlesses ok. Aber ja, ich mag es besser ifmitpresent?
Orlando

17

Sie können es prägnanter wie folgt schreiben:

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
Mir gefällt, wie sauber das ist. Ich bin allerdings neu bei Ruby. Gibt es Fallstricke oder Fälle mit fehlenden Kanten, die ich kennen sollte?
Sean

10

Einfach wie Torte:

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
Das prüft nicht, ob der Parameter vorhanden ist, sondern wird tatsächlich auf Null gesetzt.
Daemin

@Daemin In der Realität kann ein Parameter in einem Anforderungsheader jedoch nicht auf Null gesetzt werden. Es ist entweder Null oder eine Schnur.
Jacob Relkin

Ja, aber wie andere Leute bereits angegeben haben, wird es möglicherweise durch etwas anderes, ein Plugin, einen Edelstein oder Ihren eigenen Code geändert oder kann aus bizarren Gründen nicht analysiert werden.
Daemin

4
Einen Kuchen zu machen ist eigentlich kompliziert
Cesar

warum Sie nicht verwenden, es sei denn
Alireza Rahmani Khalili

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

5

Eine sehr einfache Möglichkeit, Ihren Parametern Standardwerte bereitzustellen: params[:foo] ||= 'default value'


2
Sie tun können , params.fetch(:foo, 'default value')auch
Mario Pérez

5

Ich habe dies gerade in den RubyInRails-Klassen http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F gelesen

Sie können eine blank?Methode verwenden, die äquivalent zu istparams[:one].nil? || params[:one].empty?

(z.B)

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

Perfekt, ich benutzteparams[:one].nil? || params[:one].empty?
GOXR3PLUS

Wenn der Schlüssel die richtige Methode ist, hat Ihre Methode angenommen, dass dieser Parameter bereits vorhanden ist, sodass Sie nil auf nil validieren, was funktionieren könnte, aber nicht die beste Methode ist.
Paul Brunache

3

Sie können auch Folgendes tun:

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

Ich neige dazu, die obige Lösung zu verwenden, wenn ich mehr als ein oder zwei Parameter überprüfen möchte.

.values_at gibt ein Array mit nil anstelle eines undefinierten Parameterschlüssels zurück. dh:

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

wird folgendes zurückgeben:

[3,nil,5] 

.includes? (nil) überprüft dann das Array auf Nullwerte. Es wird true zurückgegeben, wenn das Array nil enthält.

In einigen Fällen möchten Sie möglicherweise auch überprüfen, ob Parameter keine leere Zeichenfolge für einen falschen Wert enthalten.

Sie können mit diesen Werten umgehen, indem Sie den folgenden Code über der if-Anweisung hinzufügen.

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

Alles in allem würde es so aussehen:

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

Es ist wichtig zu beachten, dass delete_if Ihre Hash / Parameter ändert. Verwenden Sie sie daher mit Vorsicht.

Die obige Lösung erfordert eindeutig etwas mehr Arbeit beim Einrichten, lohnt sich jedoch, wenn Sie mehr als nur ein oder zwei Parameter überprüfen.


3

Zusätzlich zu früheren Antworten: has_key?und has_value?haben kürzere Alternativen in Form von key?und value?. Das Ruby-Team schlägt auch die Verwendung kürzerer Alternativen vor. Aus Gründen der Lesbarkeit bevorzugen einige jedoch möglicherweise längere Versionen dieser Methoden.

Daher wäre es in Ihrem Fall so etwas wie

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

NB! .key?prüft nur, ob der Schlüssel vorhanden ist und ignoriert den möglichen Wert. Zum Beispiel:

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

Folgendes mache ich:

before_action :validate_presence

und dann folgende Methoden:

    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

Einfach für das gleiche Problem zusammengesetzt:

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

In der ersten Zeile wird mithilfe der Teilmenge <= überprüft, ob unsere Zielschlüssel in den Parametern vorhanden sind. Operator. Enumerable.all? Standardmäßig wird ohne Block false zurückgegeben, wenn ein Wert null oder falsch ist.


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

Sie können auch überprüfen, ob die Parameter leer sind, indem Sie params [: two] .empty verwenden


1
Dies gilt zwar für den Fall, dass beide Parameter definiert sind. Es wird nicht der Fall behandelt, in dem einer von ihnen als falsch bewertet wird.
EmFi

0

Ich versuche eine späte, aber weitsichtige Antwort:

Wenn Sie wissen möchten, ob Werte in einem (beliebigen) Hash festgelegt sind, antworten alle oben genannten Antworten je nach Sichtweise mit true.

Wenn Sie Ihre (GET / POST ..) Parameter testen möchten, sollten Sie etwas Besonderes verwenden, das dem Wert entspricht params[:one], den Sie erwarten, beispielsweise

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

Ignorieren von Parametern (GET / POST), als ob sie nicht gesetzt wären, wenn sie nicht wie erwartet passen

Nur eine if params[:one] Erkennung mit oder ohne Null / Wahr-Erkennung ist ein Schritt, um Ihre Seite zum Hacken zu öffnen, da dies normalerweise der nächste Schritt ist, um so etwas wie select ... where params[:one] ..., ob beabsichtigt oder nicht, aktiv oder innerhalb oder nach einem Framework zu verwenden.

eine Antwort oder nur ein Hinweis

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.