【问题标题】:How to test if parameters exist in rails如何测试rails中是否存在参数
【发布时间】:2011-08-03 12:25:58
【问题描述】:

我在 Ruby on Rails 中使用 IF 语句来尝试测试是否设置了请求参数。无论是否设置了两个参数,都会触发以下 if 块的第一部分。如果同时设置了 params[:one] 和 params[:two],我怎样才能让这部分被触发?

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

【问题讨论】:

  • @Nakilon:鉴于params 是Rails 控制器方法(恰好返回一个HashWithIndifferentAccess),它与Rails 有关。

标签: ruby-on-rails ruby


【解决方案1】:

你想要has_key?:

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

只是检查if(params[:one]) 会被“there but nil”和“there but false”值所愚弄,而您正在询问存在。您可能需要区分:

  • 根本不存在。
  • 那里只有nil
  • 那里只有false
  • 只有一个空字符串。

也是。如果不详细说明您的具体情况,很难说。

【讨论】:

  • @sawa 无法传递nil 参数。如果参数存在,则为空字符串。
  • @Jacob:不能保证params 在我们检查其中的内容之前没有经过预处理。因此,我列出了可能要检查的特殊情况。最好准确地说出您的意思恕我直言。
  • @muistooshort 我的错,那是Python :(
  • 在 Rails 5 中,params 对象不再是哈希,我也没有看到 key? 方法。 edgeapi.rubyonrails.org/classes/ActionController/…
  • @muistooshort 哦,很好。对于使用不属于文档化 API 的方法,我仍然有点犹豫,但我确信这已经足够安全了。我现在一直在打电话给params.to_h.key?
【解决方案2】:

我是粉丝

params[:one].present?

只是因为它保留了params[sym] 表单,因此更易于阅读。

【讨论】:

  • 更好,更短 3 个字符,更简单。
  • 这应该是最好的有效回应!
  • 小心使用礼物?带有布尔值(未定义的方法 `present' 用于 true:TrueClass)。 has_key 接受的答案是什么?适用于所有类型。
  • 要明确这在某些情况下不起作用,例如假的。现在? => false 所以当例如通过 json body 传递参数就像可以传递布尔值一样。
  • 如果您在视图中使用此逻辑,present 将失败,因为参数数组已被调用,如果为 nil 则失败。 has_keyinstead 为您提供所需的内容。
【解决方案3】:

使用空白? http://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

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

如果为空或nil,则返回true

另外...如果您正在测试布尔值,这将不起作用..因为

>> false.blank?
=> true

在这种情况下你可以使用

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

【讨论】:

  • present?,它返回与blank?相反的结果。因此,如果您愿意,可以将 unless 转换为 if
  • @Inkling 有效,但内联 unless 没关系。但是,是的,我更喜欢 ifpresent?
【解决方案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

【讨论】:

  • 我喜欢这里的干净程度。不过,我是 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

【讨论】:

  • 那不检查参数是否存在但实际上设置为nil。
  • @Daemin 但实际上,不能在请求标头中将参数设置为 nil。它是 nil 或字符串。
  • 是的,但正如其他人所说,它可能会被其他东西、插件、gem 或您自己的代码修改,或者只是因为某些奇怪的原因而无法解析。
  • 做馅饼其实很复杂
  • 为什么你不使用除非
【解决方案6】:
if params[:one] && params[:two]
 ... do something ...
elsif params[:one]
 ... do something ...
end

【讨论】:

    【解决方案7】:

    一种为参数提供默认值的非常简单的方法:params[:foo] ||= 'default value'

    【讨论】:

    • 你也可以params.fetch(:foo, 'default value')
    【解决方案8】:

    我刚刚在 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 可能有效但不是最好的方法。
    【解决方案9】:

    您还可以执行以下操作:

    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。

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

    您可以通过在 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 会修改您的哈希/参数,因此请谨慎使用。

    上述解决方案显然需要更多的工作来设置,但如果您检查的参数不止一个或两个参数,那么它是值得的。

    【讨论】:

      【解决方案10】:

      除了以前的答案:has_key?has_value?shorter alternatives 形式为 key?value?。 Ruby 团队还 suggests 使用较短的替代方法,但对于 readability,有些人可能仍然更喜欢这些方法的较长版本。

      因此,在你的情况下,它会是这样的

      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
      

      【讨论】:

        【解决方案11】:

        只是为了同一个问题拼凑起来的:

        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
        

        第一行使用

        【讨论】:

          【解决方案12】:

          这就是我的工作,

          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
          

          【讨论】:

            【解决方案13】:

            如果您希望能够根据特定的缺失参数返回错误,而无需切换所有参数:

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

            【讨论】:

              【解决方案14】:
              if params[:one] && param[:two]
                ... excute code ..
              end
              

              也可以通过params[:two].empty检查参数是否为空

              【讨论】:

              • 虽然这涵盖了定义两个参数的情况。它不包括其中一个评估为假的情况。
              【解决方案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] ... 的东西,如果这是有意或无意的,活跃或在框架之内或之后。

              一个答案或一个提示

              【讨论】:

                猜你喜欢
                • 2011-09-07
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多