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


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.