aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorKevin Glowacz <glowacz@gmail.com>2008-07-19 15:08:53 -0500
committerJoshua Peek <josh@joshpeek.com>2008-07-19 15:10:12 -0500
commit1b4b1aa725a4f44c3473ae99b36d7cededba2bea (patch)
tree747fe8107d57a5b07ea268823b7e168e893073ab /actionpack
parent706425e154a2a2581195c98309f30a18a0002a58 (diff)
downloadrails-1b4b1aa725a4f44c3473ae99b36d7cededba2bea.tar.gz
rails-1b4b1aa725a4f44c3473ae99b36d7cededba2bea.tar.bz2
rails-1b4b1aa725a4f44c3473ae99b36d7cededba2bea.zip
Fixed index and auto index for nested fields_for [#327 state:resolved]
Signed-off-by: Joshua Peek <josh@joshpeek.com>
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb30
-rw-r--r--actionpack/test/template/form_helper_test.rb116
2 files changed, 136 insertions, 10 deletions
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 4fa46d9ee3..ada6fa2ea8 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -528,10 +528,10 @@ module ActionView
def initialize(object_name, method_name, template_object, object = nil)
@object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup
- @template_object= template_object
+ @template_object = template_object
@object = object
- if @object_name.sub!(/\[\]$/,"")
- if object ||= @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
+ if @object_name.sub!(/\[\]$/,"") || @object_name.sub!(/\[\]\]$/,"]")
+ if (object ||= @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}")) && object.respond_to?(:to_param)
@auto_index = object.to_param
else
raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
@@ -708,7 +708,7 @@ module ActionView
end
def sanitized_object_name
- @sanitized_object_name ||= @object_name.gsub(/[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
+ @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
end
def sanitized_method_name
@@ -726,6 +726,13 @@ module ActionView
def initialize(object_name, object, template, options, proc)
@object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
@default_options = @options ? @options.slice(:index) : {}
+ if @object_name.to_s.match(/\[\]$/)
+ if object ||= @template.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
+ @auto_index = object.to_param
+ else
+ raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
+ end
+ end
end
(field_helpers - %w(label check_box radio_button fields_for)).each do |selector|
@@ -738,16 +745,25 @@ module ActionView
end
def fields_for(record_or_name_or_array, *args, &block)
+ if options.has_key?(:index)
+ index = "[#{options[:index]}]"
+ elsif defined?(@auto_index)
+ self.object_name = @object_name.to_s.sub(/\[\]$/,"")
+ index = "[#{@auto_index}]"
+ else
+ index = ""
+ end
+
case record_or_name_or_array
when String, Symbol
- name = "#{object_name}[#{record_or_name_or_array}]"
+ name = "#{object_name}#{index}[#{record_or_name_or_array}]"
when Array
object = record_or_name_or_array.last
- name = "#{object_name}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
+ name = "#{object_name}#{index}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
args.unshift(object)
else
object = record_or_name_or_array
- name = "#{object_name}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
+ name = "#{object_name}#{index}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
args.unshift(object)
end
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 39649c3622..52e8bf376a 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -6,7 +6,7 @@ silence_warnings do
alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
- alias_method :secret?, :secret
+ alias_method :secret?, :secret
def new_record=(boolean)
@new_record = boolean
@@ -22,6 +22,7 @@ silence_warnings do
attr_reader :post_id
def save; @id = 1; @post_id = 1 end
def new_record?; @id.nil? end
+ def to_param; @id; end
def name
@id.nil? ? 'new comment' : "comment ##{@id}"
end
@@ -30,7 +31,6 @@ end
class Comment::Nested < Comment; end
-
class FormHelperTest < ActionView::TestCase
tests ActionView::Helpers::FormHelper
@@ -447,6 +447,117 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_nested_fields_for_with_nested_collections
+ form_for('post[]', @post) do |f|
+ concat f.text_field(:title)
+ f.fields_for('comment[]', @comment) do |c|
+ concat c.text_field(:name)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" +
+ "<input name='post[123][comment][][name]' size='30' type='text' id='post_123_comment__name' value='new comment' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index
+ form_for('post', @post, :index => 1) do |c|
+ concat c.text_field(:title)
+ c.fields_for('comment', @comment, :index => 1) do |r|
+ concat r.text_field(:name)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[1][title]' size='30' type='text' id='post_1_title' value='Hello World' />" +
+ "<input name='post[1][comment][1][name]' size='30' type='text' id='post_1_comment_1_name' value='new comment' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index
+ form_for(:post, @post, :index => 1) do |f|
+ f.fields_for(:comment, @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[1][comment][title]' size='30' type='text' id='post_1_comment_title' value='Hello World' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index_on_both
+ form_for(:post, @post, :index => 1) do |f|
+ f.fields_for(:comment, @post, :index => 5) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[1][comment][5][title]' size='30' type='text' id='post_1_comment_5_title' value='Hello World' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_auto_index
+ form_for("post[]", @post) do |f|
+ f.fields_for(:comment, @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[123][comment][title]' size='30' type='text' id='post_123_comment_title' value='Hello World' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_auto_index_on_both
+ form_for("post[]", @post) do |f|
+ f.fields_for("comment[]", @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[123][comment][123][title]' size='30' type='text' id='post_123_comment_123_title' value='Hello World' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index_and_auto_index
+ form_for("post[]", @post) do |f|
+ f.fields_for(:comment, @post, :index => 5) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ form_for(:post, @post, :index => 1) do |f|
+ f.fields_for("comment[]", @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[123][comment][5][title]' size='30' type='text' id='post_123_comment_5_title' value='Hello World' />" +
+ "</form>" +
+ "<form action='http://www.example.com' method='post'>" +
+ "<input name='post[1][comment][123][title]' size='30' type='text' id='post_1_comment_123_title' value='Hello World' />" +
+ "</form>"
+
+ assert_dom_equal expected, output_buffer
+ end
+
def test_fields_for
fields_for(:post, @post) do |f|
concat f.text_field(:title)
@@ -831,7 +942,6 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
-
protected
def comments_path(post)
"/posts/#{post.id}/comments"