8

关于参数包装状态的文档:

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

它有助于省略哪些参数散列正在被包装。动作控制器概述指南给出了这个纲要:

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"}

没有这样的运气。事实证明,ParamsWrapperusesrequest_parameters和 not params,所以不包括a_id在 POST 有效负载中意味着它没有被包装。这很令人困惑,因为params由于 URI globbing,您仍然可以看到它包含在 中,并且想知道为什么它被排除在所有事物之外。

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

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

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

4

2 回答 2

0

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

于 2014-12-26T18:03:34.130 回答
0

取决于您的具体用例,但如果您在控制器中使用强参数,您可以执行以下任一操作

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

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

params.permit(:a_id)
于 2017-02-11T12:24:35.447 回答