简体   繁体   English

具有多个对象和整数键的 Rails 4 强参数

[英]Rails 4 Strong Params with multiple objects and integer keys

I'm submitting a form with 2-4 objects at once, depending on how many the parent has.我一次提交一个包含 2-4 个对象的表单,具体取决于父对象的数量。 I realize that this is probably unconventional, but I really wanted the user to be able to edit all of the objects at once on one form.我意识到这可能是非常规的,但我真的希望用户能够在一个表单上一次编辑所有对象。 On my form, I'm doing:在我的表格上,我正在做:

<%= simple_fields_for "derps[]", derp do |f| %>

<% end %>

Then I'm doing this in the controller:然后我在控制器中这样做:

def update
  @derps = []
  @rejects = []
  derps_params.each do |key, hash|
    derp = Derp.find(key)
    derp.assign_attributes(hash)
    @rejects << derp unless derp.save
  end
  if @rejects.empty?
    redirect_to @parent, flash: {success: 'Derps were successfully updated.'}
  else
    @derps = @rejects
    render :edit
  end
end

Lets say there are two objects - the params are coming through as:假设有两个对象 - 参数通过:

"derps"=>{"1"=>{"attribute"=>"39", "another_attribute"=>"serp", "a_third_attribute"=>"yerp"}, "2"=>{"attribute"=>"30", "another_attribute"=>"49", }}

I had this working in Rails 3 without strong params.我在没有强大参数的情况下在 Rails 3 中工作。 I'm upgrading to rails 4 and I'm struggling with how to get this working - I keep getting "Unpermitted parameters: 1, 2"我正在升级到 rails 4 并且我正在努力解决如何让它工作 - 我不断收到“Unpermitted parameters: 1, 2”

I'm assuming I need to do something like:我假设我需要做类似的事情:

def mashes_params
  params.require(:derps).permit(
  id: []

or或者

def mashes_params
  params.require(:derps).permit(
  :id, 

Something along those lines, but I've tried it every way I can think of without luck.沿着这些路线的东西,但我已经尝试了所有我能想到的方法,但没有运气。

Any ideas here?这里有什么想法吗?

I've found that the command line is immensely helpful for debugging Strong Parameters in Rails 4. Here's how I tested your problem in the console:我发现命令行对于调试 Rails 4 中的强参数非常有帮助。 以下是我在控制台中测试您的问题的方法:

rails c # From within your project directory, short for 'rails console'

params = ActionController::Parameters.new( { derps: { 1 => { attribute: 39, another_attribute: "serp" }, 2 => { attribute: 30, another_attribute: 49 }  } } )

params # To make sure that the object looks the same

permitted = params.require( :derps ).permit( 1 => [ :attribute, :another_attribute ], 2 => [ :attribute, :another_attribute ] )

permitted # To see what you'd get back in your controller

Hopefully with this tool, you'll be able to debug anything that my answer didn't provide more easily than trial and error.希望使用此工具,您将能够比反复试验更轻松地调试我的答案没有提供的任何内容。

Final Edit (hopefully):最终编辑(希望如此):

Had to rethink this from the ground up.不得不从头开始重新思考这个问题。 I came to the conclusion: Since :id works as a wildcard, but is not allowed as the key of the hash, why not always make the keys 1-4, so I can whitelist them explicitly, then get the ID from a key-value in the hash, much like is done in traditional form nesting?我得出的结论是:既然 :id 可以用作通配符,但不允许作为散列的键,为什么不总是将键设为 1-4,这样我就可以明确地将它们列入白名单,然后从键中获取 ID-散列中的值,很像传统形式的嵌套? Thats how I ended up solving it.这就是我最终解决它的方式。 Here's the final implementation that I have working:这是我工作的最终实现:

<% i = @parent.derps.index(derp) + 1 %>
<%= simple_fields_for "derps[#{i}]", derp do |f| %>
  <%= f.hidden_field :id, value: derp.id %>
  <%= render "rest_of_the_fields" %>
<% end %>

Then in the controller:然后在控制器中:

def update
  @derps = []
  @rejects = []
  derp_params.each do |key, hash|
    derp = Derp.find(hash.delete("id"))
    derp.assign_attributes(hash)
    @rejects << derp unless derp.save
  end
  if @rejects.empty?
    redirect_to @parent, flash: {success: "Derps updated successfully."} 
  else
    @derps = @rejects
    render :edit
  end
end

Then here are the strong params:然后这里是强大的参数:

def derp_params
  p = [:id, :attribute_1, :another_attribute, ...]
  params.require(:derps).permit(
    "1" => p, "2" => p, "3" => p, "4" => p
  )
end

Phew.呼。 Hope this helps someone.希望这可以帮助某人。

The absolute best solution I've seen is here :我见过的绝对最佳解决方案在这里

def product_params
  properties_keys = params[:product].try(:fetch, :properties, {}).keys
  params.require(:product).permit(:title, :description, properties: properties_keys)
end

I made one more change to iterate through the unnamed keys since my property_keys have more nested keys and values:由于我的property_keys具有更多嵌套的键和值,因此我又做了一项更改以遍历未命名的键:

response_keys = params[:survey][:responses].try(:fetch, :properties, {}).keys
params.require(:survey).permit(responses: response_keys.map {|rk| [rk => [:question_id, :answer_id, :value]]})

Here is the approach I am currently using.这是我目前使用的方法。 You can permit each nested params one by one like this:您可以像这样一一允许每个嵌套参数:

params = ActionController::Parameters.new(
  "derps" => {
    "1" => {
      "attribute" => "39",
      "another_attribute" => "serp",
      "a_third_attribute" => "yerp"
    },
    "2" => {
      "attribute" => "30",
      "another_attribute" => "49"
    }
  }
)
# => <ActionController::Parameters {"derps"=>{"1"=>{"attribute"=>"39", "another_attribute"=>"serp", "a_third_attribute"=>"yerp"}, "2"=>{"attribute"=>"30", "another_attribute"=>"49"}}} permitted: false>

params.fetch(:derps).map do |i, attrs|
  [
    i,
    ActionController::Parameters.new(attrs).permit(
      :attribute,
      :another_attribute,
      :a_third_attribute,
    )
  ]
end.to_h.with_indifferent_access
#=> {"1"=><ActionController::Parameters {"attribute"=>"39", "another_attribute"=>"serp", "a_third_attribute"=>"yerp"} permitted: true>, "2"=><ActionController::Parameters {"attribute"=>"30", "another_attribute"=>"49"} permitted: true>}

Here is a sort of dirty way of accomplishing this which builds on the answer above by Greg Blass这是一种实现此目的的肮脏方法,它建立在 Greg Blass 的上述答案之上

This can handle an infinite number of indexes with nested params这可以处理无限数量的带有嵌套参数的索引

def foo_bar_params
   num_keys = params[:foo_bars].keys.size
   the_params = [:id, :attr1, :attr2, :another]
   permit_hash = {}
   i = 0
   while i < num_entries
     permit_hash[i.to_s] = the_params
     i += 1
   end
   params.require(:foo_bars).permit(permit_hash)
end

Im sure there is a fancier way to do this, but this way is readable and I can easily tell what is going on...and most importantly it works我确定有一种更好的方法可以做到这一点,但这种方法是可读的,我可以很容易地知道发生了什么……最重要的是它有效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM