【问题标题】:How to properly use params.require in Rails如何在 Rails 中正确使用 params.require
【发布时间】:2017-08-20 16:14:38
【问题描述】:

我读过several | articles 关于在 Rails 中使用 params.require(...),但没有在不平凡的真实场景中显示它们。

具体来说,会调用以下 URL:

GET http://myapp.example.com/widgets/{clientUuid}

{clientUuid} 将是一个字符串。我只想检查(从正确的控制器操作)提供的{clientUuid} 是否非空且非空。我想知道我是否可以这样做:

if params.require(params[:clientUuid]) == null
  response = { "error" => "bad client uuid" }
  render json: response, status: :bad_request
  return
end

并强制执行非空/非空?如果没有,我该怎么做才能达到我想要的结果?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    你把一个简单的 GET 请求弄乱了,并且使用了一个完全不同用途的方法。

    这个想法是 .requires 应该用于非幂等请求方法(POSTPUTPATCH),其中请求包含带有参数的主体。它允许您从参数中获取单个键并将包含的参数列入白名单 - 这与将资源名称作为根键的哈希中嵌套输入的 Rails 理念相匹配。

    在这种情况下,使用.requires 可以让您向客户端返回一个响应代码,指示无法处理请求(422 - 无法处理的实体),因为请求正文没有正确的结构。

    虽然您可以在 GET 请求中创造性地使用它,但从安静的应用程序工程的角度来看它是错误的。在您的情况下,如果 clientUuid 与记录不匹配,您应该返回 404 - Not found 响应代码。通常在 Rails 中,这是通过使用 .find 来完成的,这将引发框架捕获的 ActiveRecord::RecordNotFound 异常。

    此外,如果您首先正确声明了路线,rails 实际上会自动给出 404,因为如果缺少 id 段,请求将不匹配。

    class WidgetsController < ApplicationController
      def show
        @widget = Widget.find(params[:clientUuid])
      end
    end
    

    如果你愿意,你可以提前保释,这样如果参数不匹配条件,就永远不会查询数据库:

    class WidgetsController < ApplicationController
      def show
        raise ActiveRecord::RecordNotFound if params[:clientUuid].blank?
        @widget = Widget.find(params[:clientUuid])
      end
    end
    

    【讨论】:

      【解决方案2】:

      你可以写:

      if params[:clientUuid].blank?
        response = { "error" => "bad client uuid" }
        render json: response, status: :bad_request
        return
      end
      

      使用params.require 有点困难,因为如果参数丢失,require 会引发ActionController::ParameterMissing 异常,但允许参数返回false(我猜在您的示例中仍然无效) :

      begin
        uuid = params.require(:cliendUuid)
      rescue ActionController::ParameterMissing
        # nothing to do, just ensure the exceptions is rescued
      end
      
      unless uuid
        # handle missing uuid
      end
      

      或者:

      begin
        uuid = params.require(:cliendUuid) || raise ActionController::ParameterMissing
      rescue ActionController::ParameterMissing
        # handle missing uuid
      end
      

      【讨论】:

      • 感谢@spickermann (+1) - 很高兴了解.blank?。坚持使用params.require,任何机会你都可以更新你的代码sn-p,以展示我如何在类似的环境中使用params.require(只是好奇!)。再次感谢!
      • 我更新了我的答案,但不建议使用params.require 版本。恕我直言 require 是根据您的用例构建的。
      【解决方案3】:

      您发布的有关强参数的文章专门关于保护您的数据库数据免受用户输入的影响,通常由表单提供。

      params.require(:user).permit(:username)
      

      上面的代码指定对于模型用户只允许触摸属性用户名。如果您尝试使用任何其他属性在用户表中更新或创建用户记录,例如电子邮件,您会收到一个错误,因为电子邮件属性未被“允许”。这就是白名单的含义。您只会在createupdate 控制器方法或以某种方式修改数据的任何其他方法中看到上述代码。 (当然,一个例外是删除记录)。

      在您的示例中,该参数作为 url 的一部分提供,您也可以通过提供 params 哈希的 rails 访问该参数。但是,由于您的方法不与数据库交互,因此您不需要通过 permit 方法运行它。

      This resource 可能会有所帮助。

      【讨论】:

        猜你喜欢
        • 2014-08-06
        • 2017-04-01
        • 2016-04-20
        • 2011-10-04
        • 1970-01-01
        • 2015-07-02
        • 2016-07-04
        • 2014-03-04
        • 1970-01-01
        相关资源
        最近更新 更多