#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] ...
, предназначено это или нет, активно или внутри фреймворка или после него.
ответ или просто подсказка