aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
authorojab <ojab@ojab.ru>2015-08-30 10:02:24 +0000
committerojab <ojab@ojab.ru>2015-08-30 20:44:09 +0000
commit7089768b700f79b2ae5171dc434ef45d16d18a63 (patch)
treeb1bbfd6960f56198446b00adad1ca56245aceeda /actionview
parent79f44eb6c84fe1d7a7ba51f3f511d2e744788ef8 (diff)
downloadrails-7089768b700f79b2ae5171dc434ef45d16d18a63.tar.gz
rails-7089768b700f79b2ae5171dc434ef45d16d18a63.tar.bz2
rails-7089768b700f79b2ae5171dc434ef45d16d18a63.zip
Handle nested fields_for by adding indexes to record_name
In case of the form with nested fields_for, i. e. <%= form_for :foos, url: root_path do |f| %> <% @foos.each do |foo| %> <%= f.fields_for 'foo[]', foo do |f2| %> <%= f2.text_field :id %> <% foo.bars.each do |bar| %> <%= f2.fields_for 'bar[]', bar do |b| %> <%= b.text_field :id %> <% end %> <% end %> <% end %> <% end %> <%= f.submit %> <% end %> rails doesn't add index for 'foo' in the inner fields_for block, so field names in the outer fields_for looks like "foos[foo][#{foo_index}][id]" and in the inner "foos[foo[]][bar][#{bar_index}][id]". Submitting of such form leads to an error like: >ActionController::BadRequest (Invalid request parameters: expected Array >(got Rack::QueryParser::Params) for param `foo'): This commit adds indexes for the foos in the inner blocks, so field names become "foos[foo][#{foo_index}][bar][#{bar_index}][id]" and submitting of such form works fine as expected. Fixes #15332
Diffstat (limited to 'actionview')
-rw-r--r--actionview/lib/action_view/helpers/form_helper.rb9
-rw-r--r--actionview/test/template/form_helper_test.rb21
2 files changed, 29 insertions, 1 deletions
diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb
index 3a9acafaa2..32765c1aaa 100644
--- a/actionview/lib/action_view/helpers/form_helper.rb
+++ b/actionview/lib/action_view/helpers/form_helper.rb
@@ -1617,7 +1617,14 @@ module ActionView
@auto_index
end
- record_name = index ? "#{object_name}[#{index}][#{record_name}]" : "#{object_name}[#{record_name}]"
+ record_name = if index
+ "#{object_name}[#{index}][#{record_name}]"
+ elsif record_name.to_s.end_with?('[]')
+ record_name = record_name.to_s.sub(/(.*)\[\]$/, "[\\1][#{record_object.id}]")
+ "#{object_name}#{record_name}"
+ else
+ "#{object_name}[#{record_name}]"
+ end
fields_options[:child_index] = index
@template.fields_for(record_name, record_object, fields_options, &block)
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index aef137935a..659338e22b 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -2292,6 +2292,27 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_deep_nested_fields_for
+ @comment.save
+ form_for(:posts) do |f|
+ f.fields_for('post[]', @post) do |f2|
+ f2.text_field(:id)
+ @post.comments.each do |comment|
+ concat f2.fields_for('comment[]', comment) { |c|
+ concat c.text_field(:name)
+ }
+ end
+ end
+ end
+
+ expected = whole_form do
+ "<input name='posts[post][0][comment][1][name]' type='text' id='posts_post_0_comment_1_name' value='comment #1' />"
+ end
+
+ assert_dom_equal expected, output_buffer
+ end
+
+
def test_nested_fields_for_with_nested_collections
form_for(@post, as: 'post[]') do |f|
concat f.text_field(:title)