Как проверить, существуют ли параметры в рельсах

179

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

if (defined? params[:one]) && (defined? params[:two])
 ... do something ...
elsif (defined? params[:one])
 ... do something ...
end
Даррен
источник
10
@Nakilon: Учитывая, что paramsэто метод контроллера Rails (который возвращает HashWithIndifferentAccess), речь идет о Rails.
Му слишком коротко

Ответы:

348

Вы хотите has_key?:

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

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

  • Нет там вообще.
  • Там но nil.
  • Там но false.
  • Там только пустая строка.

также. Трудно сказать без подробностей вашей точной ситуации.

мю слишком коротка
источник
3
@sawa Невозможно передать nilпараметр. Если параметр существует, это будет пустая строка.
Джейкоб Релкин
5
@Jacob: нет никаких гарантий, которые paramsне были предварительно обработаны, пока мы не добрались до того места, где мы проверяем, что в нем. Отсюда мой список возможных особых случаев для проверки. Лучше точно сказать, что вы имеете в виду ИМХО.
мю слишком коротка
1
@muistooshort мой плохой, это был Python :(
FloatingRock
2
В Rails 5 объект params больше не является хешем, и я не вижу key?метода. edgeapi.rubyonrails.org/classes/ActionController/…
stephen.hanson
1
@muistooshort О, хорошо. Я все еще не решаюсь использовать методы, которые не являются частью документированного API, но я уверен, что это достаточно безопасно. Я звоню params.to_h.key?сейчас.
Стивен Хансон
86

Я фанат

params[:one].present?

Просто потому, что он сохраняет params[sym]форму, чтобы его было легче читать.

netricate
источник
1
Лучше, 3 символа короче, проще.
Бенгала
этот должен быть лучшим действительным ответом!
jacktrade
4
Осторожнее с подарком? с логическим значением (неопределенный метод present для true: TrueClass). Принятый ответ с has_key? работает для всех типов.
StCleezy
2
Чтобы было ясно, это не работает в некоторых случаях, например, false.present? => false Так что не будет работать, например, при передаче параметров через тело json, так как может передавать логические значения.
Джеймс
1
если вы используете эту логику в представлении, подарок потерпит неудачу, так как массив параметров уже вызывается и терпит неудачу, если nil. has_keyвместо этого дает вам то, что вы ищете.
Джером
22

использовать пустой? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

вернет true, если его пусто или ноль

также ... это не будет работать, если вы тестируете логические значения .., так как

>> false.blank?
=> true

в этом случае вы могли бы использовать

unless params[:one].to_s.blank? && params[:two].to_s.blank?
Орландо
источник
3
Или present?который возвращает противоположность blank?. Так что вы можете превратить это unlessв, ifесли хотите.
Inkling
@ 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
Мне нравится, как это чисто. Хотя я новичок в Ruby. Какие-нибудь подводные камни или пропущенные крайние случаи, о которых я должен знать?
Шон
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 В действительности, параметр не может быть установлен равным nil в заголовке запроса. Это либо ноль, либо строка.
Джейкоб Релкин
Да, но, как утверждают другие люди, он может быть изменен чем-то другим, плагином, гемом или вашим собственным кодом, или просто не может быть проанализирован по какой-то странной причине.
Daemin
4
Создание пирога на самом деле сложно
Цезарь
почему вы не используете, если
Алиреза Рахмани Халили
5
if params[:one] && params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end
fl00r
источник
5

Очень простой способ предоставить значения по умолчанию вашим параметрам: params[:foo] ||= 'default value'

chrpes
источник
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
has key - правильный метод, ваш метод предполагал, что этот параметр уже существует, поэтому вы проверяете nil на nil, что может сработать, но не лучший метод.
Пол Брунаш
3

Вы также можете сделать следующее:

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

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

.values_at возвращает и массив с nil вместо любого неопределенного ключа param. то есть:

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

вернет следующее:

[3,nil,5] 

.include? (nil) затем проверяет массив на наличие значений nil. Он вернет истину, если массив содержит ноль.

В некоторых случаях вы также можете проверить, что параметры не содержат и пустую строку на ложное значение.

Вы можете обработать эти значения, добавив следующий код над оператором "исключение".

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

первая строка проверяет, присутствуют ли наши целевые ключи в ключах params с использованием подмножества <=? оператор. Enumerable.all? без блока по умолчанию возвращает false, если любое значение равно nil или false.

okthatsneat
источник
0
if params[:one] && param[:two]
  ... excute code ..
end

Вы также можете проверить, являются ли параметры пустыми, используя params [: two] .empty

Джейсон Йост
источник
1
Хотя это охватывает случай, когда оба параметра определены. Это не распространяется на случай, когда один из них оценивается как ложный.
EmFi
0

Я стараюсь поздно, но от дальнего взгляда отвечу:

Если вы хотите узнать, заданы ли значения в (любом) хэше, все вышеприведенное ответит true, в зависимости от их точки зрения.

Если вы хотите проверить свои параметры (GET / POST ..), вы должны использовать что-то более особенное, чем то, что вы ожидаете, как значение params[:one], что-то вроде

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

игнорирование параметра (GET / POST), как будто они не установлены, если они не соответствуют ожидаемому

просто if params[:one] с обнаружением nil / true или без него - это один шаг, чтобы открыть вашу страницу для взлома, потому что, как правило, это следующий шаг, чтобы использовать что-то вроде select ... where params[:one] ..., если это предназначено или нет, активно или внутри или после фреймворка.

ответ или просто подсказка

halfbit
источник