Jak sprawdzić, czy parametry istnieją w szynach

179

Korzystam z instrukcji IF w Ruby on Rails, aby spróbować sprawdzić, czy parametry żądania są ustawione. Niezależnie od tego, czy oba parametry są ustawione, pierwsza część poniższych instrukcji, jeśli blok zostanie wyzwolony. Jak mogę uruchomić tę część WYŁĄCZNIE, jeśli oba parametry [: jeden] i parametry [: dwa] są ustawione?

if (defined? params[:one]) && (defined? params[:two])
 ... do something ...
elsif (defined? params[:one])
 ... do something ...
end
Darren
źródło
10
@Nakilon: Biorąc pod uwagę, że paramsjest to metoda kontrolera Rails (która zdarza się zwrócić HashWithIndifferentAccess), chodzi o Railsy.
mu jest za krótki

Odpowiedzi:

347

Chcesz has_key?:

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

Samo sprawdzanie if(params[:one])da się zwieść wartości „tam, ale zero” i „tam, ale fałsz” i pytasz o istnienie. Może być konieczne rozróżnienie:

  • W ogóle nie ma.
  • Tam ale nil.
  • Tam ale false.
  • Jest tylko pusty ciąg.

także. Trudno powiedzieć bez dodatkowych szczegółów na temat Twojej dokładnej sytuacji.

mu jest za krótki
źródło
3
@ sawa Nie można przekazać nilparametru. Jeśli parametr istnieje, będzie to pusty ciąg.
Jacob Relkin
5
@Jacob: Nie ma gwarancji, że paramsnie zostało wcześniej przetworzone, zanim dotrzemy do miejsca, w którym sprawdzamy, co jest w środku . Stąd moja lista możliwych specjalnych przypadków do sprawdzenia. Najlepiej powiedzieć dokładnie, co masz na myśli IMHO.
mu jest za krótki
1
@muistooshort my bad, to był Python :(
FloatingRock
2
W Rails 5 obiekt params nie jest już skrótem i nie widzę key?metody. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson
1
@muistooshort Och, miło. Wciąż waham się przed użyciem metod, które nie są częścią udokumentowanego API, ale jestem pewien, że jest to wystarczająco bezpieczne. Dzwonię params.to_h.key?teraz.
stephen.hanson
86

Jestem fanem

params[:one].present?

Tylko dlatego, że zachowuje params[sym]formularz, dzięki czemu jest łatwiejszy do odczytania.

Netricate
źródło
1
Lepsze, 3 znaki krótsze, prostsze.
Bengala,
ten powinien być najlepszą prawidłową odpowiedzią!
jacktrade
4
Ostrożnie za pomocą prezentu? z logicznymi wartościami (niezdefiniowana metoda `present 'dla true: TrueClass). Akceptowana odpowiedź z has_key? działa dla wszystkich typów.
StCleezy,
2
Dla jasności nie działa to w niektórych przypadkach jako np. False.present? => false Więc nie zadziała, gdy np. przekaże parametry przez ciało Jsona, ponieważ może przekazać booleany.
James
1
jeśli używasz tej logiki w widoku, teraźniejszość nie powiedzie się, ponieważ tablica parametrów jest już wywoływana i zawiedzie, jeśli zero. has_keyzamiast tego daje ci to, czego szukasz.
Jerome
22

użyć pustego? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

zwróci true, jeśli jest puste lub zero

także ... to nie zadziała, jeśli testujesz wartości boolowskie .. od tego czasu

>> false.blank?
=> true

w takim przypadku możesz użyć

unless params[:one].to_s.blank? && params[:two].to_s.blank?
Orlando
źródło
3
Lub present?który zwraca przeciwieństwo blank?. Więc można włączyć, że unlessw produkt if, jeśli chciał.
Inkling
@Inkling to działa, ale wstawka unlessjest w porządku. Ale tak, chciałbym lepiej ifzpresent?
Orlando
18

Możesz napisać to bardziej zwięźle, jak poniżej:

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
Zack Xu
źródło
1
Podoba mi się, jak to jest czyste. Ale jestem nowy w Ruby. Jakieś pułapki lub przypadki nieobecności na krawędzi, o których powinienem wiedzieć?
Sean
10

Proste jak ciasto:

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
Jacob Relkin
źródło
3
To nie sprawdza, czy parametr tam jest, ale w rzeczywistości jest ustawione na zero.
Daemin,
@Dememin W rzeczywistości jednak parametr nie może być ustawiony na zero w nagłówku żądania. Jest to zero lub ciąg znaków.
Jacob Relkin,
Tak, ale jak stwierdzili inni, może zostać zmodyfikowany przez coś innego, wtyczkę, klejnot lub własny kod, lub po prostu nie może zostać przetworzony z jakiegoś dziwnego powodu.
Daemin,
4
Robienie ciasta jest w rzeczywistości skomplikowane
Cesar
dlaczego nie używasz, chyba że
Alireza Rahmani Khalili
5
if params[:one] && params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end
fl00r
źródło
5

Bardzo prosty sposób na dostarczenie wartości domyślnych swoim parametrom: params[:foo] ||= 'default value'

chrpes
źródło
2
można zrobić params.fetch(:foo, 'default value')zbyt
Mario Perez
5

Właśnie przeczytałem to na klasach RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

możesz użyć blank? metody równoważnej doparams[:one].nil? || params[:one].empty?

(na przykład)

if params[:one].blank? 
  # do something if not exist
else
  # do something if exist
end
Basil Mariano
źródło
Idealnie, params[:one].nil? || params[:one].empty?
używałem
klucz jest właściwą metodą, twoja metoda przyjęła, że ​​ten parametr już istnieje, więc sprawdzasz zero na zero, co może działać, ale nie najlepsza metoda.
Paul Brunache
3

Możesz także wykonać następujące czynności:

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

Zazwyczaj używam powyższego rozwiązania, gdy chcę sprawdzić więcej niż jeden lub dwa parametry.

.values_at zwraca i tablicę z zerem w miejsce dowolnego niezdefiniowanego klucza param. to znaczy:

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

zwróci następujące elementy:

[3,nil,5] 

.include? (zero) następnie sprawdza tablicę pod kątem jakichkolwiek wartości zero. Zwróci wartość true, jeśli tablica zawiera zero.

W niektórych przypadkach możesz również chcieć sprawdzić, czy parametry nie zawierają pustego łańcucha o wartości false.

Można obsłużyć te wartości, dodając następujący kod nad instrukcją chyba.

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

wszystko razem wyglądałoby to tak:

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

Ważne jest, aby pamiętać, że delete_if zmodyfikuje twój skrót / parametry, więc używaj go ostrożnie.

Powyższe rozwiązanie najwyraźniej wymaga nieco więcej pracy, ale jest tego warte, jeśli sprawdzasz więcej niż tylko jeden lub dwa parametry.

Greg L.
źródło
3

Oprócz poprzednich odpowiedzi: has_key?i has_value?mają krótsze alternatywy w postaci key?i value?. Zespół Ruby sugeruje także stosowanie krótszych alternatyw, ale ze względu na czytelność niektórzy mogą nadal preferować dłuższe wersje tych metod.

Dlatego w twoim przypadku byłoby to coś w rodzaju

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

NB! .key?sprawdzi tylko, czy klucz istnieje i zignoruje jakąkolwiek możliwą wartość. Na przykład:

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
Andres Ehrenpreis
źródło
2

Oto co robię

before_action :validate_presence

a następnie następujące metody:

    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
Parth Modi
źródło
1

Właśnie złożyłem to razem dla tego samego problemu:

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

pierwsza linia sprawdza, czy nasze klucze docelowe są obecne w kluczach parametrów za pomocą podzbioru <=? operator. Enumerable.all? bez bloku domyślnie zwraca wartość false, jeśli dowolna wartość jest równa zero lub fałsz.

okthatsneat
źródło
0
if params[:one] && param[:two]
  ... excute code ..
end

Możesz również sprawdzić, czy parametry są puste, używając params [: two] .empty

Jason Yost
źródło
1
Chociaż dotyczy to przypadku, w którym zdefiniowano oba parametry. Nie obejmuje przypadku, w którym jeden z nich uznaje się za fałszywy.
EmFi
0

Próbuję spóźnić się, ale z daleka odpowiedź:

Jeśli chcesz wiedzieć, czy wartości w (dowolnym) haszu są ustawione, wszystkie powyższe odpowiedzi są prawdziwe, w zależności od ich punktu widzenia.

Jeśli chcesz przetestować swoje parametry (GET / POST ..), powinieneś użyć czegoś bardziej specjalnego od tego, czego oczekujesz, że będzie to wartość params[:one], na przykład

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

ignorowanie parametru (GET / POST) tak, jakby nie były ustawione, jeśli nie pasują zgodnie z oczekiwaniami

tylko if params[:one] z wykrywaniem zerowym / prawdziwym lub bez niego to jeden krok, aby otworzyć stronę do hakowania, ponieważ zazwyczaj jest to następny krok, aby użyć czegoś takiegoselect ... where params[:one] ... , jeśli jest to zamierzone lub nie, aktywne lub w ramach lub po frameworku.

odpowiedź lub tylko podpowiedź

półbitka
źródło