【问题标题】:Why doesn't Rails parameter wrapping include things globbed from the URI?为什么 Rails 参数包装不包含来自 URI 的内容?
【发布时间】:2012-08-22 05:09:31
【问题描述】:

docs on parameter wrapping 状态:

将参数散列包装成嵌套散列。这将允许客户端提交 POST 请求而无需指定任何根元素。

它有助于省略 哪些 参数散列正在被包装。 Action Controller overview guide 给出了这个破败:

Rails 在params 散列中收集与请求一起发送的所有参数,无论它们是作为查询字符串的一部分还是作为帖子正文发送。 [...] query_parameters 散列包含作为查询字符串的一部分发送的参数,而 request_parameters 散列包含作为帖子正文的一部分发送的参数。 path_parameters 哈希包含的参数被路由识别为通向此特定控制器和操作的路径的一部分。

当您使用 RESTful 资源和路由时,乐趣就会发生。假设您有一个模型 A,其中包含多个 B; B因此有一个外键a_id

POST /as/1/bs 的有效负载为空(因为 B 没有其他字段)。假设a_idattr_accessible,人们可能会假设a_id 将被包装在b 对象中。相反,您会看到:

Processing by BsController#create as HTML
  Parameters: {"b"=>{}, "a_id" => "1"}

没有这样的运气。事实证明,ParamsWrapper uses request_parameters 而不是params,因此在 POST 有效负载中不包括 a_id 意味着它不会被包装。这很令人困惑,因为由于 URI 通配,您仍然会看到它包含在 params 中,并且想知道为什么它被排除在所有事物之外。

这里有什么好的理由使用request_parameters 而不是params

我可以理解,从“REST 哲学”的角度来看,如果我们假设有效负载包含整个对象,它会更加纯粹,但这本质上意味着 URI 中的 a_id 被完全忽略,这似乎可惜了。

tl;dr: ParamsWrapper 使用 request_parameters 作为参数源,因此跳过了 URI 全局变量。这是 Rails 的错误吗?纯 REST 倡导者可能会说不,但实用主义建议是。

【问题讨论】:

  • 您好!你想好如何解决这个问题了吗?
  • @dan:不幸的是,自从我发布这个问题几个月后,我就没有使用过 Rails,所以我什么都没有!

标签: ruby-on-rails actioncontroller


【解决方案1】:

据我了解,a_id 未包含在“b”的哈希中的原因是我们需要该 id 值来首先检查记录是否存在于我们的数据库中。这样,我们可以简单地拒绝请求中的其他参数。根据不将其包含在'b'哈希中的原因:它可以防止意外。以这种情况为例:假设有人正在更新表单并将完整的“b”哈希作为参数传递给模型对象。现在,当我们调用 model_object.save 时,它​​可能会将记录保存在我们的数据库中,而不是更新旧记录,这将是一个安全威胁(如果对象已被较早初始化,则可能发生)。不是一个完整的证明方案,但在编码时确实会发生事故,它可以帮助我们防止此类事故。

【讨论】:

    【解决方案2】:

    取决于您的具体用例,但如果您在控制器中使用强参数,您可以这样做

    params[:b][:a_id] = params[:a_id]
    params.require(:b).permit(:a_id)
    

    或者完全跳过“require”方法:

    params.permit(:a_id)
    

    【讨论】:

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