diff options
author | José Valim <jose.valim@gmail.com> | 2011-11-27 23:59:36 -0800 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2011-11-27 23:59:36 -0800 |
commit | ad5c8b0d5228c32355621162e1be211208ae3f5c (patch) | |
tree | ebcf797affbb51373cd065f26f076e4877e93f8f /actionpack | |
parent | 5cf56a4e7711b952d86d5c9c563bd05d2313883b (diff) | |
parent | 25592569638689f9d863f21862b1f23b5b390833 (diff) | |
download | rails-ad5c8b0d5228c32355621162e1be211208ae3f5c.tar.gz rails-ad5c8b0d5228c32355621162e1be211208ae3f5c.tar.bz2 rails-ad5c8b0d5228c32355621162e1be211208ae3f5c.zip |
Merge pull request #3776 from nashby/add-namespace-to-form
add namespace options to form_for
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG.md | 10 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/form_helper.rb | 11 | ||||
-rw-r--r-- | actionpack/test/template/form_helper_test.rb | 76 |
3 files changed, 95 insertions, 2 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index fe422f71d5..314aa7181c 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,15 @@ ## Rails 3.2.0 (unreleased) ## +* You can provide a namespace for your form to ensure uniqueness of id attributes on form elements. + The namespace attribute will be prefixed with underscore on the generate HTML id. *Vasiliy Ermolovich* + + Example: + + <%= form_for(@offer, :namespace => 'namespace') do |f| %> + <%= f.label :version, 'Version' %>: + <%= f.text_field :version %> + <% end %> + * Refactor ActionDispatch::ShowExceptions. Controller is responsible for choice to show exceptions. *Sergey Nartimov* It's possible to override +show_detailed_exceptions?+ in controllers to specify which requests should provide debugging information on errors. diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 4471a2b541..6c97d75922 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -158,6 +158,9 @@ module ActionView # * <tt>:url</tt> - The URL the form is submitted to. It takes the same # fields you pass to +url_for+ or +link_to+. In particular you may pass # here a named route directly as well. Defaults to the current action. + # * <tt>:namespace</tt> - A namespace for your form to ensure uniqueness of + # id attributes on form elements. The namespace attribute will be prefixed + # with underscore on the generate HTML id. # * <tt>:html</tt> - Optional HTML attributes for the form tag. # # Also note that +form_for+ doesn't create an exclusive scope. It's still @@ -385,7 +388,7 @@ module ActionView action, method = object.respond_to?(:persisted?) && object.persisted? ? [:edit, :put] : [:new, :post] options[:html].reverse_merge!( :class => as ? "#{as}_#{action}" : dom_class(object, action), - :id => as ? "#{as}_#{action}" : dom_id(object, action), + :id => as ? "#{as}_#{action}" : [options[:namespace], dom_id(object, action)].compact.join("_").presence, :method => method ) @@ -971,6 +974,7 @@ 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 + @object_name.sub!(/\[\]$/,"") || @object_name.sub!(/\[\]\]$/,"]") @object = retrieve_object(object) @auto_index = retrieve_autoindex(Regexp.last_match.pre_match) if Regexp.last_match @@ -989,6 +993,7 @@ module ActionView add_default_name_and_id_for_value(tag_value, name_and_id) options.delete("index") + options.delete("namespace") options["for"] ||= name_and_id["id"] if block_given? @@ -1195,6 +1200,7 @@ module ActionView options["name"] ||= tag_name + (options['multiple'] ? '[]' : '') options["id"] = options.fetch("id"){ tag_id } end + options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence end def tag_name @@ -1253,7 +1259,7 @@ module ActionView @nested_child_index = {} @object_name, @object, @template, @options, @proc = object_name, object, template, options, proc @parent_builder = options[:parent_builder] - @default_options = @options ? @options.slice(:index) : {} + @default_options = @options ? @options.slice(:index, :namespace) : {} 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 @@ -1280,6 +1286,7 @@ module ActionView fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options? fields_options[:builder] ||= options[:builder] fields_options[:parent_builder] = self + fields_options[:namespace] = fields_options[:parent_builder].options[:namespace] case record_name when String, Symbol diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 0758106a40..ad876df65d 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -935,6 +935,82 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_namespace + form_for(@post, :namespace => 'namespace') do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.check_box(:secret) + end + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'put') do + "<input name='post[title]' size='30' type='text' id='namespace_post_title' value='Hello World' />" + + "<textarea name='post[body]' id='namespace_post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[secret]' type='hidden' value='0' />" + + "<input name='post[secret]' checked='checked' type='checkbox' id='namespace_post_secret' value='1' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_form_for_with_namespace_with_label + form_for(@post, :namespace => 'namespace') do |f| + concat f.label(:title) + concat f.text_field(:title) + end + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'put') do + "<label for='namespace_post_title'>Title</label>" + + "<input name='post[title]' size='30' type='text' id='namespace_post_title' value='Hello World' />" + end + + assert_dom_equal expected, output_buffer + end + + def test_two_form_for_with_namespace + form_for(@post, :namespace => 'namespace_1') do |f| + concat f.label(:title) + concat f.text_field(:title) + end + + expected_1 = whole_form('/posts/123', 'namespace_1_edit_post_123', 'edit_post', 'put') do + "<label for='namespace_1_post_title'>Title</label>" + + "<input name='post[title]' size='30' type='text' id='namespace_1_post_title' value='Hello World' />" + end + + assert_dom_equal expected_1, output_buffer + + form_for(@post, :namespace => 'namespace_2') do |f| + concat f.label(:title) + concat f.text_field(:title) + end + + expected_2 = whole_form('/posts/123', 'namespace_2_edit_post_123', 'edit_post', 'put') do + "<label for='namespace_2_post_title'>Title</label>" + + "<input name='post[title]' size='30' type='text' id='namespace_2_post_title' value='Hello World' />" + end + + assert_dom_equal expected_2, output_buffer + end + + def test_fields_for_with_namespace + @comment.body = 'Hello World' + form_for(@post, :namespace => 'namespace') do |f| + concat f.text_field(:title) + concat f.text_area(:body) + concat f.fields_for(@comment) { |c| + concat c.text_field(:body) + } + end + + expected = whole_form('/posts/123', 'namespace_edit_post_123', 'edit_post', 'put') do + "<input name='post[title]' size='30' type='text' id='namespace_post_title' value='Hello World' />" + + "<textarea name='post[body]' id='namespace_post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" + + "<input name='post[comment][body]' size='30' type='text' id='namespace_post_comment_body' value='Hello World' />" + end + + assert_dom_equal expected, output_buffer + end + def test_submit_with_object_as_new_record_and_locale_strings old_locale, I18n.locale = I18n.locale, :submit |