Reputation: 3059
I'm using an IF statement in Ruby on Rails to try and test if request parameters are set. Regardless of whether or not both parameters are set, the first part of the following if block gets triggered. How can I make this part ONLY get triggered if both params[:one] and params[:two] is set?
if (defined? params[:one]) && (defined? params[:two])
... do something ...
elsif (defined? params[:one])
... do something ...
end
Upvotes: 207
Views: 241478
Reputation: 3324
If you want to be able to return an error based on the specific missing parameter without having to switch through all of them:
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
Upvotes: 2
Reputation: 434575
You want has_key?
:
if(params.has_key?(:one) && params.has_key?(:two))
Just checking if(params[:one])
will get fooled by a "there but nil" and "there but false" value and you're asking about existence. You might need to differentiate:
nil
.false
.as well. Hard to say without more details of your precise situation.
Upvotes: 406
Reputation: 1728
I am a fan of
params[:one].present?
Just because it keeps the params[sym]
form so it's easier to read.
Upvotes: 109
Reputation: 2675
I just read this on RubyInRails classes http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F
you can use blank?
method which is equivalent to params[:one].nil? || params[:one].empty?
(e.g)
if params[:one].blank?
# do something if not exist
else
# do something if exist
end
Upvotes: 4
Reputation: 2219
In addition to previous answers: has_key?
and has_value?
have shorter alternatives in form of key?
and value?
. Ruby team also suggests using shorter alternatives, but for readability some might still prefer longer versions of these methods.
Therefore in your case it would be something like
if params.key?(:one) && params.key?(:two)
... do something ...
elsif params.key?(:one)
... do something ...
end
NB! .key?
will just check if the key exists and ignores the whatever possible value. For ex:
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
Upvotes: 3
Reputation: 1813
Here's what I do,
before_action :validate_presence
and then following methods:
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
Upvotes: 2
Reputation: 11872
You can write it more succinctly like the following:
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
Upvotes: 24
Reputation: 21
Just pieced this together for the same problem:
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
the first line checks if our target keys are present in the params' keys using the <= subset? operator. Enumerable.all? without block per default returns false if any value is nil or false.
Upvotes: 2
Reputation: 381
You can also do the following:
unless params.values_at(:one, :two, :three, :four).includes?(nil)
... excute code ..
end
I tend to use the above solution when I want to check to more then one or two params.
.values_at returns and array with nil in the place of any undefined param key. i.e:
some_hash = {x:3, y:5}
some_hash.values_at(:x, :random, :y}
will return the following:
[3,nil,5]
.includes?(nil) then checks the array for any nil values. It will return true is the array includes nil.
In some cases you may also want to check that params do not contain and empty string on false value.
You can handle those values by adding the following code above the unless statement.
params.delete_if{|key,value| value.blank?}
all together it would look like this:
params.delete_if{|key,value| value.blank?}
unless params.values_at(:one, :two, :three, :four).includes?(nil)
... excute code ..
end
It is important to note that delete_if will modify your hash/params, so use with caution.
The above solution clearly takes a bit more work to set up but is worth it if you are checking more then just one or two params.
Upvotes: 4
Reputation: 3939
I try a late, but from far sight answer:
If you want to know if values in a (any) hash are set, all above answers a true, depending of their point of view.
If you want to test your (GET/POST..) params, you should use something more special to what you expect to be the value of params[:one]
, something like
if params[:one]~=/ / and params[:two]~=/[a-z]xy/
ignoring parameter (GET/POST) as if they where not set, if they dont fit like expected
just a if params[:one]
with or without nil/true detection is one step to open your page for hacking, because, it is typically the next step to use something like select ... where params[:one] ...
, if this is intended or not, active or within or after a framework.
an answer or just a hint
Upvotes: 0
Reputation: 9692
use blank? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F
unless params[:one].blank? && params[:two].blank?
will return true if its empty or nil
also... that will not work if you are testing boolean values.. since
>> false.blank?
=> true
in that case you could use
unless params[:one].to_s.blank? && params[:two].to_s.blank?
Upvotes: 25
Reputation: 695
A very simple way to provide default values to your params: params[:foo] ||= 'default value'
Upvotes: 6
Reputation: 163228
Simple as pie:
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
Upvotes: 10
Reputation: 4937
if params[:one] && param[:two]
... excute code ..
end
You can also check if the parameters are empty by using params[:two].empty
Upvotes: 0
Reputation: 83680
if params[:one] && params[:two]
... do something ...
elsif params[:one]
... do something ...
end
Upvotes: 5