From 00b26532f05283d2b160308522d1bd2146d6ac18 Mon Sep 17 00:00:00 2001 From: Mauro George Date: Mon, 8 Dec 2014 20:22:36 -0200 Subject: Add a hidden_field on the file_field This will avoid a error be raised when the only input on the form is the `file_field`. --- actionview/CHANGELOG.md | 6 ++++++ actionview/lib/action_view/helpers/form_helper.rb | 17 +++++++++++++++ .../lib/action_view/helpers/tags/file_field.rb | 13 +++++++++++ actionview/test/template/form_helper_test.rb | 25 +++++++++++++++++----- 4 files changed, 56 insertions(+), 5 deletions(-) (limited to 'actionview') diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index d71f29d7b0..4fa468dd91 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -3,4 +3,10 @@ *Angelo Capilleri* +* 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* + + 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') # # => + # + # ==== 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 + # include_hidden: false 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..02585fa0ae 100644 --- a/actionview/lib/action_view/helpers/tags/file_field.rb +++ b/actionview/lib/action_view/helpers/tags/file_field.rb @@ -2,6 +2,19 @@ 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..0b3d78ea9b 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 = '' + 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 = '' + 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 = '' + assert_dom_equal expected, file_field("user", "avatar", 'include_hidden' => false) + end + + def test_file_field_has_no_size + expected = '' assert_dom_equal expected, file_field("user", "avatar") end def test_file_field_with_multiple_behavior - expected = '' + expected = '' assert_dom_equal expected, file_field("import", "file", :multiple => true) end def test_file_field_with_multiple_behavior_and_explicit_name - expected = '' + expected = '' 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 - "" + "" 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 - "" + "" end assert_dom_equal expected, output_buffer -- cgit v1.2.3