Rails 参数中的 dup 和 clone 存在明显问题

Lau*_*ent 3 ruby ruby-on-rails

我在 Rails 控制器中。我尝试获取一些params数据并更改一些数据来更新模型,但我也想保持原始数据params不变。

合乎逻辑的方法是使用cloneordup但无论我尝试什么,它都会失败并更改原始哈希。

# Original product_params which is set as params.require(:product)
{"name"=>"Product 2",
 "brand"=>"Brand 2",
 "desc"=>"Placeat a sunt eos incidunt temporibus.\r\n\r\nReprehenderit repudiandae amet quibusdam dolorem et. Itaque commodi at.",
 "hs_code"=>"12212121",
 "options_attributes"=>
  {"0"=>{"name"=>"hkjlVariation 4", "suboptions_attributes"=>{"0"=>{"name"=>"Chkjlhoice 0", "id"=>"582209026b710eded24ecd12"}}, "id"=>"582209026b710eded24ecd13"},
   "1"=>
    {"name"=>"hhVhariation h5kkk",
     "suboptions_attributes"=>{"0"=>{"name"=>"Choice 0kh", "id"=>"582209026b710eded24ecd14"}, "1"=>{"name"=>"hkjChoice 1", "id"=>"582209026b710eded24ecd16"}, "2"=>{"name"=>"kkk"}},
     "id"=>"582209026b710eded24ecd15"},
   "2"=>{"name"=>"lh", "suboptions_attributes"=>{"0"=>{"name"=>"klhj"}}}}}

# Method to change the `suboptions_attributes` to `nil`
def product_params_without_suboptions
  copy = product_params.dup
  copy.tap do |product_param|
    product_param[:options_attributes].each do |key, option_attribute|
      unless option_attribute[:suboptions_attributes].nil?
        option_attribute[:suboptions_attributes] = nil
      end
    end
  end
end

# We define product_params
def product_params
  params.require(:product).permit!
end
Run Code Online (Sandbox Code Playgroud)

的结果product_params_without_suboptions是正确的。它设置了所有的option_attributenil但是当我尝试打电话时,params或者product_params它也在那里改变了。dup 为什么不在这里工作?

Lau*_*ent 6

工作溶液

经过一番调查,我意识到 params 及其亲属是一个ActionController::Parameters类,而不是一个简单的哈希输出requireexcept用 、 等操作它是合乎逻辑的。我首先认为它完全像哈希一样,但事实并非如此。

在其上执行clone, dup,deep_dup只会复制该类,并且由于 Rails 的魔力,更改此副本中的任何内容都将导致全局更改。我不知道这种行为的确切原因,但我猜想存在一些类变量/单例模式

我发现的最简单的解决方案是将其转换为哈希通过,to_h这样就解决了这个问题。您可以执行params_hash = params.to_h然后操作散列,它不会对原始params对象产生任何影响。