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
Darren
sumber
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.

mu terlalu pendek
sumber
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.

netricate
sumber
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?
Orlando
sumber
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
Zack Xu
sumber
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
Jacob Relkin
sumber
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
fl00r
sumber
5

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

chrpes
sumber
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
Basil Mariano
sumber
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.

Greg L.
sumber
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
Andres Ehrenpreis
sumber
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
Parth Modi
sumber
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.

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

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

Jason Yost
sumber
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

setengah bit
sumber