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

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

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

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

Комментарии:

1. @Nakilon: Учитывая, что params это метод Rails controller (который возвращает HashWithIndifferentAccess), речь идет о Rails.

Ответ №1:

Вы хотите has_key? :

 if(params.has_key?(:one) amp;amp; params.has_key?(:two))
  

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

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

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

Комментарии:

1. @sawa Невозможно передать nil параметр. Если параметр существует, это будет пустая строка.

2. @Jacob: Нет гарантии, что params это не было предварительно обработано до того, как мы перейдем к проверке того, что в нем есть. Отсюда мой список возможных особых случаев для проверки. Лучше всего точно сказать, что вы имеете в виду, ИМХО.

3. @muistoosh short я виноват, это был Python 🙁

4. В Rails 5 объект params больше не является хэшем, и я не вижу key? метода. edgeapi.rubyonrails.org/classes/ActionController /…

5. @muistoosh short О, здорово. Я все еще немного не решаюсь использовать методы, которые не являются частью документированного API, но я уверен, что это достаточно безопасно. Я уже звонил params.to_h.key? .

Ответ №2:

Я фанат

params[:one].present?

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

Комментарии:

1. Лучше, на 3 символа короче, проще.

2. этот ответ должен быть наилучшим допустимым!

3. Осторожно используйте present? с помощью логических значений (неопределенный метод `present’ для true: TrueClass). Принятый ответ с помощью has_key? работает для всех типов.

4. Для ясности, это не работает в некоторых случаях, например, false.present? => false, поэтому не будет работать, например, при передаче параметров через тело json, поскольку может передавать логические значения.

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

Ответ №3:

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

 unless params[:one].blank? amp;amp; params[:two].blank?
  

вернет true, если оно пустое или равно нулю

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

 >> false.blank?
=> true
  

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

 unless params[:one].to_s.blank? amp;amp; params[:two].to_s.blank?
  

Комментарии:

1. Или present? который возвращает противоположное blank? . Так что вы могли бы превратить это unless в if , если бы захотели.

2. @Inkling это работает, но встроенное unless это нормально. Но да, мне больше нравится if с present?

Ответ №4:

Вы можете написать это более кратко, например, следующим образом:

 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. Какие-либо подводные камни или пропущенные крайние случаи, о которых я должен знать?

Ответ №5:

Проще простого:

 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
  

Комментарии:

1. Это не проверяет, есть ли параметр, но на самом деле имеет значение nil.

2. @Daemin Однако на самом деле параметру нельзя присвоить значение nil в заголовке запроса. Это либо nil, либо строка.

3. Да, но, как заявляли другие люди, это может быть изменено чем-то другим, плагином, драгоценным камнем или вашим собственным кодом, или просто не выполняется синтаксический анализ по какой-то странной причине.

4. Создание pie на самом деле сложно

5. почему вы не используете, если

Ответ №6:

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

Комментарии:

1. вы тоже могли бы сделать params.fetch(:foo, 'default value')

Ответ №7:

 if params[:one] amp;amp; params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end
  

Ответ №8:

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

 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] 
  

.включает в себя?(nil) затем проверяет массив на наличие любых нулевых значений. Он вернет true, если массив содержит nil.

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

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

 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 изменит ваш хэш / параметры, поэтому используйте с осторожностью.

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

Ответ №9:

Я только что прочитал это о классах 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
  

Комментарии:

1. Идеально, я использовал params[:one].nil? || params[:one].empty?

2. has key — правильный метод, ваш метод предполагает, что этот параметр уже существует, поэтому вы проверяете nil на nil, что могло бы сработать, но не лучший метод.

Ответ №10:

В дополнение к предыдущим ответам: has_key? и has_value? имеют более короткие альтернативы в виде key? и value? . Команда Ruby также предлагает использовать более короткие альтернативы, но для удобства чтения некоторые все же могут предпочесть более длинные версии этих методов.

Поэтому в вашем случае это было бы что-то вроде

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

ПРИМЕЧАНИЕ! .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
  

Ответ №11:

Если вы хотите иметь возможность возвращать ошибку на основе конкретного отсутствующего параметра без необходимости переключаться между ними всеми:

 required_params = [:one, :two, :three]
required_params.each do |param|
  if params.has_key?(param)
    render json: { errors: "Missing parameter #{param.to_s}." }, :status => :bad_request 
    return
  end
end
  

Комментарии:

1. Определение blank? , если использовать его таким образом, привело бы к некоторым серьезным проблемам во время выполнения, если необходимым параметром является пустой массив, пустая строка, пустой хэш, логическое значение FALSE или nil. Что вам нужно, так это has_key? метод, как в принятом ответе. Этот ответ опасен.

2. @Vlad хороший улов, я обновлю ответ.

Ответ №12:

Просто собрал это вместе для решения одной и той же проблемы:

 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)) amp;amp;
  params.values.all?
end
  

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

Ответ №13:

Вот что я делаю,

 before_action :validate_presence
  

а затем следующие методы:

     def check_presence
  params[:param1].present? amp;amp; params[:param2].present?
 end

 def validate_presence
  if !check_presence
    render json:  {
                      error:  {
                                message: "Bad Request, parameters missing.",
                                status: 500
                              }
                    }
  end
 end
  

Ответ №14:

 if params[:one] amp;amp; param[:two]
  ... excute code ..
end
  

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

Комментарии:

1. Хотя это относится к случаю, когда определены оба параметра. Это не распространяется на случай, когда один из них принимает значение false.

Ответ №15:

Я пытаюсь ответить с опозданием, но издалека:

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

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

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

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

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

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