1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

add namespace options to form_for

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
This commit is contained in:
Vasiliy Ermolovich 2011-11-27 23:41:23 +03:00
parent e7e046fa1c
commit fb8b555c49
2 changed files with 85 additions and 2 deletions

View file

@ -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

View file

@ -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