Rails:调用ActionController::P arameter#permit()在不使用它返回的对象时会达到什



我知道调用params.permit(:foo)会创建一个:foo白名单的新ActionController::Parameters实例,以便您可以使用它实例化模型。但是为什么话语CMS中的以下代码调用它而不使用其返回值呢?

discourse/app/controllers/drafts_controller.rb: Github

class DraftsController < ApplicationController
# [...]
def index
# [...]
params.permit(:offset)
params.permit(:limit)
# [...]
opts = {
# [...]
offset: params[:offset],
limit: params[:limit]
}
stream = Draft.stream(opts)

这看起来确实令人困惑,我同意。

#permit的实现和ActionController::Params的文档来看,这可能会根据配置action_on_unpermitted_parameters而表现不同,它接受:log:raise作为值,默认情况下是nil的。

action_on_unpermitted_parameters = nil时:

调用params.permit(:foo)将返回仅使用该键标记为允许的新ActionController::Parameters实例。

如果不使用返回值,则此调用毫无意义,因为没有副作用。接收器未发生突变。

action_on_unpermitted_parameters = :log时:

其行为与上述相同,但具有记录所有不允许的键的副作用:

irb> ActionController::Parameters.action_on_unpermitted_parameters = :log
=> :log
irb> params = ActionController::Parameters.new(username: 'john', offset: 5, bogus: 'foo')
=> <ActionController::Parameters {"username"=>"john", "offset"=>5, "bogus"=>"foo"} permitted: false>
irb> params.require(:username)
=> "john"
irb> params.permit(:offset)
Unpermitted parameters: :username, :bogus
=> <ActionController::Parameters {"offset"=>5} permitted: true>
irb> params.permit(:limit)
Unpermitted parameters: :username, :offset, :bogus
=> <ActionController::Parameters {} permitted: true>

如您所见,对于每个permit调用,您都会获得不同的日志。因此,仅当该控制器中的代码包含所有允许(和必需(的参数时,这才有意义:

irb> params.permit(:username, :offset, :limit)
Unpermitted parameter: :bogus
=> <ActionController::Parameters {"username"=>"john", "offset"=>5} permitted: true>

action_on_unpermitted_parameters = :raise时:

这里的效果是,当参数包含不允许的键时,它会引发。与:log类似,这也只有在指定了所有允许(和必需(的键时才有意义:

irb> ActionController::Parameters.action_on_unpermitted_parameters = :raise
=> :raise
irb> params = ActionController::Parameters.new(username: 'john', offset: 5, bogus: 'foo')
=> <ActionController::Parameters {"username"=>"john", "offset"=>5, "bogus"=>"foo"} permitted: false>
irb> params.require(:username)
=> "john"
irb> params.permit(:offset)
Traceback (most recent call last):
1: from (irb):19
ActionController::UnpermittedParameters (found unpermitted parameters: :username, :bogus)
irb> params.permit(:limit)
Traceback (most recent call last):
2: from (irb):20
1: from (irb):20:in `rescue in irb_binding'
ActionController::UnpermittedParameters (found unpermitted parameters: :username, :offset, :bogus)

将其与包含所有键形成对比:

irb> params.permit(:username, :offset, :limit)
Traceback (most recent call last):
2: from (irb):21
1: from (irb):21:in `rescue in irb_binding'
ActionController::UnpermittedParameters (found unpermitted parameter: :bogus)

话虽如此,我在Discourse的代码库中找不到任何action_on_unpermitted_parameters。因此,该值nil,因此我得出结论,该控制器操作中的#permit在功能方面没有影响。

它可以作为文档的约定存在,其中首先列出所有必需的参数,然后列出所有可选参数。

更深入地挖掘,这些#permit调用是在此提交中引入的,当时它仍然是一个名为strong_parameters的独立 gem。#permit在那颗宝石中的行为与今天相同。这让我认为该提交的作者误解了strong_parameters的 API。

最新更新