为什么Rails参数包装不包含来自URI的全局内容?

时间:2012-08-22 05:09:32

标签: ruby-on-rails actioncontroller

docs on parameter wrapping州:

  

将参数哈希包装到嵌套哈希中。这将允许客户端提交POST请求,而无需指定任何根元素。

有助于删除正在包装哪些参数哈希。 Action Controller overview guide给出了这次破产:

  

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

使用RESTful资源和路由时会发生这种乐趣。假设你有一个模型A has_many Bs;因此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意味着它不会被包装。这非常令人困惑,因为你仍然会在params中看到它包含在URI通道中,并且想知道为什么它被排除在外。

在这里使用request_parameters而非params是否有充分的理由?

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

tl; dr: ParamsWrapper使用request_parameters作为参数源,因此会跳过URI-globbed变量。这是一个Rails错误吗?纯REST倡导者可能会说不,但实用主义暗示是。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

或完全跳过“require”方法:

params.permit(:a_id)