如何测试Rails中是否存在参数


179

我在Ruby on Rails中使用IF语句来尝试测试是否设置了请求参数。无论是否同时设置了两个参数,如果触发了块,则下面的第一部分。如果同时设置了params [: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有关。
亩太短了

Answers:


344

您要has_key?

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

仅仅检查if(params[:one])就会被“只有零”和“只有虚假”的值所愚弄,并且您正在询问存在性。您可能需要区分:

  • 根本没有。
  • 那里但是nil
  • 那里但是false
  • 那里只有一个空字符串。

也一样 如果没有您的具体情况的更多细节,很难说。


3
@sawa无法传递nil参数。如果该参数存在,它将是一个空字符串。
2011年

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?
stephen.hanson,2016年

85

我是的粉丝

params[:one].present?

仅仅因为它保留了params[sym]表格,所以更易于阅读。


1
更好,短3个字符,更简单。
孟加拉邦

这应该是最好的有效回应!
jacktrade

4
小心使用礼物吗?带有布尔值(对于true:TrueClass,未定义的方法“ present”)。has_key接受的答案?适用于所有类型。
StCleezy

2
需要明确的是,在某些情况下,例如false.present不能正常工作?=> false因此,例如在通过json主体传递参数(如可以传递布尔值)时将不起作用。
詹姆斯

如果在视图中使用此逻辑,则将失败,因为参数数组已被调用;如果为nil,则失败。has_key相反,它会为您提供所需的东西。
杰罗姆'18

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为。
2014年

@Inkling可以,但是内联unless也可以。但是,是的,我喜欢更好ifpresent?
奥兰多

17

您可以像下面这样简洁地编写它:

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的新手。我应该知道任何陷阱或遗漏的情况吗?
肖恩(Sean)

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
那不会检查参数是否存在,但实际上设置为nil。

@Daemin但实际上,不能在请求标头中将参数设置为nil。它可以是nil或字符串。
Jacob Relkin 2011年

是的,但是正如其他人所说,它可能会被其他东西,插件,gem或您自己的代码修改,或者由于某些奇怪的原因而无法解析。

4
制作馅饼实际上很复杂
Cesar 2015年

为什么您不使用除非
Alireza Rahmani Khalili

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?
太好了

has key是正确的方法,您的方法假定该参数已经存在,因此您要在nil上验证nil,这可能有效,但不是最佳方法。
Paul Brunache

3

您还可以执行以下操作:

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

当我想检查一两个以上的参数时,我倾向于使用上述解决方案。

.values_at返回并使用nil代替任何未定义的参数键的数组。即:

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

将返回以下内容:

[3,nil,5] 

.includes?(nil)然后检查数组中是否有nil值。如果数组包含nil,它将返回true。

在某些情况下,您可能还想检查参数是否不包含空值是否为假字符串。

您可以通过在except语句上方添加以下代码来处理这些值。

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

注意!.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的键中?操作员。可枚举的吗?如果没有值为nil或false,则默认情况下不带块默认返回false。


0
if params[:one] && param[:two]
  ... excute code ..
end

您也可以使用params [:two] .empty检查参数是否为空。


1
虽然这涵盖了定义两个参数的情况。它不涵盖其中之一评估为假的情况。
EmFi 2011年

0

我尝试了很晚,但从远景来看答案:

如果您想知道是否设置了(任何)哈希中的值,则以上所有内容都会根据其观点回答为true。

如果您想测试(GET / POST ..)参数,则应使用比预期值更特殊的params[:one]东西,例如

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

忽略参数(GET / POST),好像没有设置参数,如果参数不合适

只是if params[:one] 有或无零/真检测是一步打开网页的黑客攻击,因为它通常是下一步使用类似select ... where params[:one] ...,如果这是有意或无意,主动或内或之后的框架。

答案或提示

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.