Як перевірити наявність параметрів у рейках


179

Я використовую оператор IF в Ruby on Rails, щоб спробувати перевірити, чи встановлені параметри запиту. Незалежно від того, встановлені або не обидва параметри, перша частина наступного, якщо блок спрацьовує. Як я можу змусити цю частину ТОЛЬКО спрацьовувати, якщо встановлено обидва парами [: одна] та парами [: два]?

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

10
@Nakilon: Враховуючи, що paramsце метод контролера Rails (який трапляється повертати HashWithIndifferentAccess), мова йде про Rails.
mu занадто короткий

Відповіді:


348

Ви хочете has_key?:

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

Просто перевірка if(params[:one])буде обдуреною значень "там, але нуль" і "там, але неправда", і ви запитаєте про існування. Вам може знадобитися диференціювати:

  • Зовсім не там.
  • Там але nil.
  • Там але false.
  • Там, але порожня рядок.

також. Важко сказати без деталей вашої точної ситуації.


3
@sawa Неможливо передати nilпараметр. Якщо параметр існує, це буде порожній рядок.
Яків Рєлкін

5
@Jacob: Немає жодної гарантії, paramsяка не була попередньо оброблена, перш ніж дійти до місця, де ми перевіряємо, що в ній є. Звідси мій перелік можливих особливих випадків для перевірки. Найкраще точно сказати, що ти маєш на увазі IMHO.
mu занадто короткий

1
@muistooshort мій поганий, це був Python :(
FloatingRock

2
У Rails 5 об'єкт params більше не є хешем, і я не бачу key?методу. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson

1
@muistooshort О, приємно. Я все ще трохи не вагаюся використовувати методи, які не входять до документально підтвердженого API, але я впевнений, що це досить безпечно. Я зараз дзвоню params.to_h.key?.
stephen.hanson

86

Я фанат

params[:one].present?

Просто тому, що вона зберігає params[sym]форму, тому її легше читати.


1
Краще, на 3 символи коротше, простіше.
Бенгала

це має бути найкращим правильним відгуком!
джек-трейд

4
Обережне використання подарунка? з булевими (невизначений метод `присутній 'для true: TrueClass). Прийнята відповідь has_key? працює для всіх типів.
StCleezy

2
Щоб зрозуміти, це не працює в деяких випадках, наприклад, як false.present? => false Так не працюватимуть, наприклад, при передачі параметрів через тіло json, як можуть передавати булеві.
Джеймс

1
якщо ви використовуєте цю логіку в представленні, представлення буде невдалим, оскільки масив параметрів вже викликається і не працює, якщо нуль. has_keyнатомість дає вам те, що ви шукаєте.
Ієронім

22

використовувати порожнє? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

повернеться істинним, якщо його порожнє або нульове

також ... це не спрацює, якщо ви тестуєте булеві значення .. оскільки

>> false.blank?
=> true

у такому випадку ви могли б скористатися

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

3
Або present?який повертає протилежне blank?. Таким чином, ви могли б перетворити це unlessна те, ifякщо хочете.
Інклінг

@Inkling, що працює, але вбудовано unlessвсе нормально. Але так, я краще люблю ifзpresent?
Орландо

18

Ви можете написати це більш лаконічно так:

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
Мені подобається, наскільки це чисто. Я все-таки новачок у Рубі. Про якісь підводні камені або пропущені кромки, про які я повинен знати?
Шон

10

Простий як пиріг:

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
Це не перевіряє, чи є параметр, але насправді встановлено на нуль.
Daemin

@Daemin Насправді, параметр не може бути встановлений на нуль у заголовку запиту. Це або нуль, або рядок.
Яків Релькін

Так, але, як заявили інші люди, він може бути модифікований чимось іншим, плагіном, самоцвітом або власним кодом, або просто не зможе розібратися з якоїсь химерної причини.
Daemin

4
Приготування пирога насправді складне
Сезар

чому ви не користуєтесь хіба що
Аліреза Рахмані Халілі

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

5

Дуже простий спосіб надати параметри значення за замовчуванням: params[:foo] ||= 'default value'


2
ви могли б зробити params.fetch(:foo, 'default value')теж
Маріо Перес,

5

Я щойно прочитав це на класах RubyInRails http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

ви можете використовувати blank?метод, еквівалентнийparams[:one].nil? || params[:one].empty?

(наприклад)

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

Ідеально, я використовувавparams[:one].nil? || params[:one].empty?
GOXR3PLUS

ключ є правильним методом, ваш метод припускає, що цей парам вже існує, тому ви перевіряєте нуль на nil, який може працювати, але не найкращий метод.
Пол Брунаш

3

Ви також можете зробити наступне:

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

Я схильний використовувати вищезазначене рішення, коли хочу перевірити більше одного або двох парам.

.values_at повертається і масив з нулем замість будь-якого невизначеного ключа парама. тобто:

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

поверне наступне:

[3,nil,5] 

.includes? (nil) потім перевіряє масив на наявність будь-яких нульових значень. Він повернеться істинним, якщо масив включає нуль.

У деяких випадках ви також можете перевірити, чи парами не містять і порожній рядок на помилковому значенні.

Ви можете обробити ці значення, додавши наступний код над оператором if.

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

все разом це виглядатиме так:

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

Важливо зазначити, що delete_if змінить ваші хеші / парами, тому використовуйте з обережністю.

Наведене вище рішення очевидно потребує трохи більше роботи, щоб налаштувати, але воно того варте, якщо ви перевіряєте більше, ніж лише один чи два параметри.


3

На додаток до попередніх відповідей: has_key?і has_value?мати короткі альтернативи у формі key?та value?. Команда Ruby також пропонує використовувати більш короткі альтернативи, але для читабельності деякі можуть все ж віддавати перевагу більш тривалим версіям цих методів.

Тому у вашому випадку це було б щось подібне

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

NB! .key?просто перевірить, чи існує ключ, і ігнорує все можливе значення. Наприклад:

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

Ось що я роблю,

before_action :validate_presence

а потім наступними методами:

    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

Просто вирішили це разом із тієї ж проблеми:

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

перший рядок перевіряє, чи є наші цільові клавіші в клавішах парам, використовуючи <= підмножину? оператор. Численні. всі? без блоку за замовчуванням повертає значення false, якщо будь-яке значення є нульовим або хибним.


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

Ви також можете перевірити, чи параметри порожні, використовуючи параметри [: two] .empty


1
Хоча це стосується випадку, коли визначені обидва параметра. Він не охоплює випадок, коли один з них оцінює помилкове.
EmFi

0

Я пробую пізно, але здалеку відповідаю:

Якщо ви хочете знати, чи встановлені значення в (будь-якому) хеші, все вище відповідає істинним, залежно від їх точки зору.

Якщо ви хочете перевірити свої параметри (GET / POST ..), вам слід скористатися чимось більш спеціальним у тому, що ви очікуєте, що це значення params[:one], щось на зразок

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

ігноруючи параметр (GET / POST) так, ніби вони там, де не встановлено, якщо вони не відповідають таким, як очікувалося

просто if params[:one] виявлення нуля / справжнього виявлення - це один крок, щоб відкрити вашу сторінку для злому, оскільки, як правило, наступним кроком є ​​використання чогось типуselect ... where params[:one] ... , якщо це призначено чи ні, активного або в рамках або після нього.

відповідь або просто натяк

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.