如何从 ActionController::Parameters 中删除对象?

How can I remove objects from ActionController::Parameters?

我正在尝试从我的 ActionController::Parameters 对象中删除一个元素,但它没有像我预期的那样工作。我的report_params对象如下,

<ActionController::Parameters {"id"=>"51956915", "author_id"=>"1", "workout_attributes"=><ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true> permitted: true>

我想执行以下操作从对象中删除 workout_attributes

report_params.extract!(:workout_attributes)

还有这个returns下面的信息,但是当我重新运行时它仍然存在report_params

<ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true>

当我在控制台中重新运行 report_params 时...

<ActionController::Parameters {"id"=>"51956915", "author_id"=>"1", "workout_attributes"=><ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true> permitted: true>

更新 这是来自控制器的 report_params 方法:

def report_params
  params.require(:report).permit(:id, :author_id, 
        workout_attributes: [:player_id, :report_id, :date]
        )
end

所以我不允许编辑 report_params 对象,我需要制作它的副本,然后将该副本传递给操作中的更新函数吗?或者这里有什么我做的不正确?谢谢!

更新 "Working" 解决方案

我发现如果我执行以下操作,本质上是制作参数的副本,然后进行编辑和传递 - 它有效。但是,如果可以用实际的原始参数对象来完成,这似乎是丑陋的代码。

  modified_report_params = report_params
  modified_report_params.extract!(:workout_attributes)

  respond_to do |format|
    format.js do
      if @report.update(modified_report_params)
      # ...
  end

允许参数创建一个新对象:

params = ActionController::Parameters.new(a: 1, b: 2)
params.object_id
#=> 70277626506220
params.permit(:a, :b).object_id #new object created
#=> 70277626332020

如您所见,每次调用 report_params 时都会从 params 创建一个新对象。要解决您的问题,您可以改变 params 本身:

params.extract!(:workout_attributes)

或者,通过使用记忆:

def report_params
  @report_params ||= params
    .require(:report)
    .permit(:id, :author_id, workout_attributes: [:player_id, :report_id, :date])
end
report_params.extract!(:workout_attributes)
#=><ActionController::Parameters {"player_id"=>"14155", "date"=>"2017-10-09", "report_id"=>"51956915"} permitted: true>

只需使用 Hash#except 而不是 #extract!

except(*keys)

Returns a hash that includes everything except given keys.

respond_to do |format|
  format.js do
    if @report.update(report_params.except(:workout_attributes))
      # ...
    end
  end
end

这对我有用:

params.except(:password)