aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/helpers
diff options
context:
space:
mode:
Diffstat (limited to 'actionview/lib/action_view/helpers')
-rw-r--r--actionview/lib/action_view/helpers/form_helper.rb17
-rw-r--r--actionview/lib/action_view/helpers/tags/file_field.rb15
2 files changed, 32 insertions, 0 deletions
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