Rails 4强参数,包含多个对象和整数键

Gre*_*ass 7 ruby-on-rails strong-parameters ruby-on-rails-4

我一次提交一个包含2-4个对象的表单,具体取决于父项的数量.我意识到这可能是非常规的,但我真的希望用户能够在一个表单上一次编辑所有对象.在我的表格上,我正在做:

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

<% end %>
Run Code Online (Sandbox Code Playgroud)

然后我在控制器中这样做:

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
Run Code Online (Sandbox Code Playgroud)

让我们说有两个对象 - params正在通过:

"derps"=>{"1"=>{"attribute"=>"39", "another_attribute"=>"serp", "a_third_attribute"=>"yerp"}, "2"=>{"attribute"=>"30", "another_attribute"=>"49", }}
Run Code Online (Sandbox Code Playgroud)

我在Rails 3中工作时没有强大的参数.我正在升级到rails 4,我正在努力解决这个问题 - 我不断获得"未经许可的参数:1,2"

我假设我需要做以下事情:

def mashes_params
  params.require(:derps).permit(
  id: []
Run Code Online (Sandbox Code Playgroud)

要么

def mashes_params
  params.require(:derps).permit(
  :id, 
Run Code Online (Sandbox Code Playgroud)

沿着这些方向的东西,但我已经尝试过每一个我能想到没有运气的方式.

这里有什么想法?

s_d*_*lan 5

我发现命令行对于在 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
Run Code Online (Sandbox Code Playgroud)

希望使用此工具,您将能够比反复试验更轻松地调试我的答案没有提供的任何内容。


Gre*_*ass 1

最终编辑(希望如此):

必须从头开始重新考虑这个问题。我得出的结论是:既然 :id 可以作为通配符,但不允许作为散列的键,为什么不总是将键设置为 1-4,这样我可以将它们显式列入白名单,然后从键中获取 ID -散列中的值,很像传统形式的嵌套吗?这就是我最终解决它的方法。这是我正在工作的最终实现:

<% 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 %>
Run Code Online (Sandbox Code Playgroud)

然后在控制器中:

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
Run Code Online (Sandbox Code Playgroud)

然后是强参数:

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

唷。希望这对某人有帮助。