Cara menguji apakah parameter ada di rel


179

Saya menggunakan pernyataan IF di Ruby on Rails untuk mencoba dan menguji apakah parameter permintaan ditetapkan. Terlepas dari apakah kedua parameter ditetapkan atau tidak, bagian pertama berikut ini jika blok dipicu. Bagaimana saya bisa membuat bagian ini HANYA dipicu jika kedua params [: satu] dan params [: dua] diatur?

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

10
@ Nakilon: Mengingat bahwa paramsini adalah metode pengendali Rails (yang terjadi untuk mengembalikan HashWithIndifferentAccess), ini adalah tentang Rails.
mu terlalu pendek

Jawaban:


348

Anda ingin has_key?:

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

Hanya memeriksa if(params[:one])akan tertipu oleh nilai "di sana tetapi nihil" dan "di sana tetapi salah" dan Anda bertanya tentang keberadaan. Anda mungkin perlu membedakan:

  • Tidak ada sama sekali.
  • Tapi disana nil.
  • Tapi disana false.
  • Ada tetapi string kosong.

demikian juga. Sulit dikatakan tanpa detail lebih banyak tentang situasi Anda yang sebenarnya.


3
@sawa Tidak mungkin untuk melewati nilparameter. Jika parameter ada, itu akan menjadi string kosong.
Jacob Relkin

5
@ Jacob: Tidak ada jaminan yang paramsbelum diproses sebelum kita sampai di tempat kami memeriksa apa yang ada di dalamnya. Oleh karena itu daftar kemungkinan kasus khusus untuk diperiksa. Terbaik untuk mengatakan apa yang Anda maksud IMHO.
mu terlalu pendek

1
@muistooshort salahku, itu adalah Python :(
FloatingRock

2
Di Rails 5, objek params tidak lagi hash, dan saya tidak melihat key?metode. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson

1
@muistooshort Oh, bagus. Saya masih ragu untuk menggunakan metode yang bukan bagian dari API yang terdokumentasi, tapi saya yakin itu cukup aman. Saya sudah menelepon params.to_h.key?untuk saat ini.
stephen.hanson

86

Saya penggemar

params[:one].present?

Hanya karena menyimpan params[sym]formulir sehingga lebih mudah dibaca.


1
Lebih baik, 3 karakter lebih pendek, lebih sederhana.
Bengala

yang ini harus menjadi respons valid terbaik!
jacktrade

4
Hati-hati menggunakan hadiah? dengan booleans (metode undefined `present 'for true: TrueClass). Jawaban yang diterima dengan has_key? bekerja untuk semua tipe.
StCleezy

2
Agar jelas ini tidak berfungsi dalam beberapa kasus sebagai mis false.present? => false Jadi tidak akan berfungsi ketika misal: melewatkan parameter melalui json body seperti yang dapat melewati booleans.
James

1
jika Anda menggunakan logika ini dalam tampilan, present akan gagal karena array parameter sudah dipanggil dan gagal jika nil. has_keyalih-alih memberi Anda apa yang Anda cari.
Jerome

22

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

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

akan mengembalikan true jika kosong atau nol

juga ... itu tidak akan berfungsi jika Anda menguji nilai boolean .. sejak

>> false.blank?
=> true

dalam hal ini Anda bisa menggunakan

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

3
Atau present?yang mengembalikan kebalikan dari blank?. Jadi Anda bisa mengubahnya unlessmenjadi ifjika Anda mau.
Inkling

@Inkling bekerja, tapi inline unlesstidak apa-apa. Tapi ya, saya lebih suka ifdenganpresent?
Orlando

18

Anda dapat menulisnya dengan lebih ringkas seperti berikut:

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
Saya suka betapa bersihnya ini. Saya baru mengenal Ruby. Adakah perangkap atau kasus tepi yang terlewat yang harus saya ketahui?
Sean

10

Sederhana seperti pai:

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
Itu tidak memeriksa apakah parameter ada di sana tetapi sebenarnya diatur ke nol.
Daemin

@Daemin Pada kenyataannya, parameter tidak dapat diatur ke nol di header permintaan. Entah nol atau string.
Jacob Relkin

Ya, tetapi seperti yang dinyatakan orang lain, mungkin dimodifikasi oleh sesuatu yang lain, sebuah plugin, permata, atau kode Anda sendiri, atau hanya gagal untuk menguraikan karena alasan yang aneh.
Daemin

4
Membuat pai sebenarnya rumit
Cesar

mengapa Anda tidak menggunakan kecuali
Alireza Rahmani Khalili

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

5

Cara yang sangat sederhana untuk memberikan nilai default ke params Anda: params[:foo] ||= 'default value'


2
Anda bisa melakukan params.fetch(:foo, 'default value')terlalu
Mario Pérez

5

Saya baru saja membaca ini di kelas RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

Anda dapat menggunakan blank?metode yang setara denganparams[:one].nil? || params[:one].empty?

(misalnya)

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

Sempurna, saya menggunakanparams[:one].nil? || params[:one].empty?
GOXR3PLUS

memiliki kunci adalah metode yang tepat, metode Anda mengasumsikan bahwa param ini sudah ada sehingga Anda memvalidasi nil on nil yang dapat bekerja tetapi bukan metode terbaik.
Paul Brunache

3

Anda juga dapat melakukan hal berikut:

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

Saya cenderung menggunakan solusi di atas ketika saya ingin memeriksa lebih dari satu atau dua params.

.values_at kembali dan array dengan nihil menggantikan kunci param yang tidak terdefinisi. yaitu:

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

akan mengembalikan yang berikut:

[3,nil,5] 

.includes? (nil) lalu periksa array untuk nilai nil. Ini akan mengembalikan true adalah array termasuk nil.

Dalam beberapa kasus, Anda mungkin juga ingin memeriksa bahwa params tidak mengandung dan mengosongkan string pada nilai yang salah.

Anda dapat menangani nilai-nilai itu dengan menambahkan kode berikut di atas pernyataan kecuali.

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

semuanya akan terlihat seperti ini:

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

Penting untuk dicatat bahwa delete_if akan memodifikasi hash / params Anda, jadi gunakan dengan hati-hati.

Solusi di atas jelas membutuhkan sedikit lebih banyak pekerjaan untuk diatur tetapi sepadan jika Anda memeriksa lebih dari satu atau dua params saja.


3

Selain jawaban sebelumnya: has_key?dan has_value?memiliki alternatif yang lebih pendek dalam bentuk key?dan value?. Tim Ruby juga menyarankan untuk menggunakan alternatif yang lebih pendek, tetapi untuk keterbacaan beberapa mungkin masih lebih suka versi yang lebih panjang dari metode ini.

Karena itu dalam kasus Anda itu akan menjadi seperti

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

NB! .key?hanya akan memeriksa apakah kunci ada dan mengabaikan nilai apa pun yang mungkin. Misalnya:

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

Inilah yang saya lakukan,

before_action :validate_presence

dan kemudian metode berikut:

    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

Hanya menyatukan ini untuk masalah yang sama:

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

baris pertama memeriksa apakah kunci target kami ada di kunci params menggunakan <= subset? operator. Enumerable.all? tanpa blok per default mengembalikan false jika ada nilai nil atau salah.


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

Anda juga dapat memeriksa apakah parameternya kosong dengan menggunakan params [: two] .empty


1
Sementara ini mencakup kasus di mana kedua parameter didefinisikan. Itu tidak mencakup kasus di mana salah satu dari mereka bernilai false.
EmFi

0

Saya mencoba yang terlambat, tetapi dari pandangan jauh jawaban:

Jika Anda ingin tahu apakah nilai dalam hash (apa saja) ditetapkan, semua jawaban di atas benar, tergantung dari sudut pandang mereka.

Jika Anda ingin menguji (GET / POST ..) params Anda, Anda harus menggunakan sesuatu yang lebih khusus untuk apa yang Anda harapkan menjadi nilai params[:one], sesuatu seperti

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

mengabaikan parameter (GET / POST) seolah-olah mereka di mana tidak diatur, jika mereka tidak sesuai seperti yang diharapkan

hanya if params[:one] dengan atau tanpa deteksi nil / benar adalah satu langkah untuk membuka halaman Anda untuk peretasan, karena, biasanya langkah berikutnya untuk menggunakan sesuatu seperti select ... where params[:one] ..., apakah ini dimaksudkan atau tidak, aktif atau di dalam atau setelah kerangka kerja.

jawaban atau hanya sebuah petunjuk

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.