aboutsummaryrefslogtreecommitdiffstats
path: root/actionview
diff options
context:
space:
mode:
authorRafael Mendonça França <rafaelmfranca@gmail.com>2015-01-02 13:54:26 -0300
committerRafael Mendonça França <rafaelmfranca@gmail.com>2015-01-02 13:57:33 -0300
commitc455817804e4df64c46c17a0cdec0e5a1ca5ba2e (patch)
treefc567eb385b14ebc8ca92bdc6972026bf6c586cd /actionview
parent8b3cd74b8a09ef85a43d7631bb062a9ec7f57227 (diff)
parent00b26532f05283d2b160308522d1bd2146d6ac18 (diff)
downloadrails-c455817804e4df64c46c17a0cdec0e5a1ca5ba2e.tar.gz
rails-c455817804e4df64c46c17a0cdec0e5a1ca5ba2e.tar.bz2
rails-c455817804e4df64c46c17a0cdec0e5a1ca5ba2e.zip
Merge pull request #17973 from maurogeorge/file_field_hidden_field
Generate a hidden_tag when using a file_field
Diffstat (limited to 'actionview')
-rw-r--r--actionview/CHANGELOG.md6
-rw-r--r--actionview/lib/action_view/helpers/form_helper.rb17
-rw-r--r--actionview/lib/action_view/helpers/tags/file_field.rb15
-rw-r--r--actionview/test/template/form_helper_test.rb25
4 files changed, 58 insertions, 5 deletions
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index d71f29d7b0..6abfd8b364 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,6 +1,12 @@
+* Add a `hidden_field` on the `file_field` to avoid raise a error when the only
+ input on the form is the `file_field`.
+
+ *Mauro George*
+
* Add an explicit error message, in `ActionView::PartialRenderer` for partial
`rendering`, when the value of option `as` has invalid characters.
*Angelo Capilleri*
+
Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/actionview/CHANGELOG.md) for previous changes.
diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb
index c4371dc705..e3a8f998a8 100644
--- a/actionview/lib/action_view/helpers/form_helper.rb
+++ b/actionview/lib/action_view/helpers/form_helper.rb
@@ -854,6 +854,23 @@ module ActionView
#
# file_field(:attachment, :file, class: 'file_input')
# # => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
+ #
+ # ==== Gotcha
+ #
+ # The HTML specification says when nothing is select on a file field web browsers do not send any value to server.
+ # Unfortunately this introduces a gotcha:
+ # if an +User+ model has a +avatar+ field, and in the form none file is selected no +avatar+ parameter is sent. So,
+ # any mass-assignment idiom like
+ #
+ # @user.update(params[:user])
+ #
+ # wouldn't update avatar.
+ #
+ # To prevent this the helper generates an auxiliary hidden field before
+ # every file field. The hidden field has the same name as file field and blank value.
+ #
+ # In case if you don't want the helper to generate this hidden field you can specify
+ # <tt>include_hidden: false</tt> option.
def file_field(object_name, method, options = {})
Tags::FileField.new(object_name, method, self, options).render
end
diff --git a/actionview/lib/action_view/helpers/tags/file_field.rb b/actionview/lib/action_view/helpers/tags/file_field.rb
index 476b820d84..e6a1d9c62d 100644
--- a/actionview/lib/action_view/helpers/tags/file_field.rb
+++ b/actionview/lib/action_view/helpers/tags/file_field.rb
@@ -2,6 +2,21 @@ module ActionView
module Helpers
module Tags # :nodoc:
class FileField < TextField # :nodoc:
+
+ def render
+ options = @options.stringify_keys
+
+ if options.fetch("include_hidden", true)
+ add_default_name_and_id(options)
+ options[:type] = "file"
+ tag("input", name: options["name"], type: "hidden", value: "") + tag("input", options)
+ else
+ options.delete("include_hidden")
+ @options = options
+
+ super
+ end
+ end
end
end
end
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index 1459b9f02a..fff1e1e572 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -472,18 +472,33 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, text_field(object_name, "title")
end
- def test_file_field_has_no_size
+ def test_file_field_does_generate_a_hidden_field
+ expected = '<input name="user[avatar]" type="hidden" value="" /><input id="user_avatar" name="user[avatar]" type="file" />'
+ assert_dom_equal expected, file_field("user", "avatar")
+ end
+
+ def test_file_field_does_not_generate_a_hidden_field_if_included_hidden_option_is_false
+ expected = '<input id="user_avatar" name="user[avatar]" type="file" />'
+ assert_dom_equal expected, file_field("user", "avatar", include_hidden: false)
+ end
+
+ def test_file_field_does_not_generate_a_hidden_field_if_included_hidden_option_is_false_with_key_as_string
expected = '<input id="user_avatar" name="user[avatar]" type="file" />'
+ assert_dom_equal expected, file_field("user", "avatar", "include_hidden" => false)
+ end
+
+ def test_file_field_has_no_size
+ expected = '<input name="user[avatar]" type="hidden" value="" /><input id="user_avatar" name="user[avatar]" type="file" />'
assert_dom_equal expected, file_field("user", "avatar")
end
def test_file_field_with_multiple_behavior
- expected = '<input id="import_file" multiple="multiple" name="import[file][]" type="file" />'
+ expected = '<input name="import[file][]" type="hidden" value="" /><input id="import_file" multiple="multiple" name="import[file][]" type="file" />'
assert_dom_equal expected, file_field("import", "file", :multiple => true)
end
def test_file_field_with_multiple_behavior_and_explicit_name
- expected = '<input id="import_file" multiple="multiple" name="custom" type="file" />'
+ expected = '<input name="custom" type="hidden" value="" /><input id="import_file" multiple="multiple" name="custom" type="file" />'
assert_dom_equal expected, file_field("import", "file", :multiple => true, :name => "custom")
end
@@ -1719,7 +1734,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts/123", "create-post", "edit_post", method: "patch", multipart: true) do
- "<input name='post[file]' type='file' id='post_file' />"
+ "<input name='post[file]' type='hidden' value='' /><input name='post[file]' type='file' id='post_file' />"
end
assert_dom_equal expected, output_buffer
@@ -1735,7 +1750,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts/123", "edit_post_123", "edit_post", method: "patch", multipart: true) do
- "<input name='post[comment][file]' type='file' id='post_comment_file' />"
+ "<input name='post[comment][file]' type='hidden' value='' /><input name='post[comment][file]' type='file' id='post_comment_file' />"
end
assert_dom_equal expected, output_buffer