为什么Rails参数包装不包括从URI中抓取的内容?

8

参数包装的文档指出:

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

它有益地省略了要包装哪个参数哈希。操作控制器概述指南提供了以下说明:

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

当您使用RESTful资源和路由时会有趣。假设您有一个模型A,它有许多B;B因此具有外键a_id。
您可以使用空载荷(因为B没有其他字段)POST /as/1/bs。假设a_id是attr_accessible,则可能会认为a_id将被包裹在一个b对象中。而实际上您将会看到:
Processing by BsController#create as HTML
  Parameters: {"b"=>{}, "a_id" => "1"}

没这么幸运。原来ParamsWrapper使用request_parameters而不是params,所以在POST负载中不包括a_id意味着它没有被包装。这很令人困惑,因为你仍然可以看到它包含在params中,由于URI globbing的缘故,你会想知道为什么它被排除了。

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

我可以理解,从"REST哲学"的角度来看,如果我们假设负载包含整个对象,那么更纯粹,但这实际上意味着URI中的a_id完全被忽略了,这似乎很遗憾。

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


你好!你解决了如何绕过这个问题吗? - Dan
1
@dan:不幸的是,自从我发了这个问题几个月后,我就没再使用过Rails,所以我没有任何东西可提供! - Asherah
2个回答

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

0

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

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

或者干脆跳过 "require" 方法:

params.permit(:a_id)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接