From b17b980a15ee4a5f2f629d91c6fa6ca7db74daa8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 16 Sep 2010 23:31:57 -0700 Subject: file_field makes the enclosing form multipart --- actionpack/CHANGELOG | 2 + actionpack/lib/action_view/helpers/form_helper.rb | 55 +++++++++++++++-------- actionpack/test/template/form_helper_test.rb | 18 ++++++++ 3 files changed, 56 insertions(+), 19 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 0ec42cc6de..6f8314109b 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.1.0 (unreleased)* +* file_field automatically adds :multipart => true to the enclosing form. [Santiago Pastorino] + * Renames csrf_meta_tag -> csrf_meta_tags, and aliases csrf_meta_tag for backwards compatibility. [fxn] * Add Rack::Cache to the default stack. Create a Rails store that delegates to the Rails cache, so by default, whatever caching layer you are using will be used diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb index 79a9d997dd..59d90f24f1 100644 --- a/actionpack/lib/action_view/helpers/form_helper.rb +++ b/actionpack/lib/action_view/helpers/form_helper.rb @@ -317,8 +317,11 @@ module ActionView options[:html] ||= {} options[:html][:remote] = options.delete(:remote) - output = form_tag(options.delete(:url) || {}, options.delete(:html) || {}) - output << fields_for(object_name, object, options, &proc) + builder = instantiate_builder(object_name, object, options, &proc) + fields_for = capture(builder, &proc) + default_options = builder.multipart? ? { :multipart => true } : {} + output = form_tag(options.delete(:url) || {}, default_options.merge!(options.delete(:html) || {})) + output << fields_for output.safe_concat('') end @@ -529,22 +532,7 @@ module ActionView # <% end %> # <% end %> def fields_for(record, record_object = nil, options = nil, &block) - raise ArgumentError, "Missing block" unless block_given? - - options, record_object = record_object, nil if record_object.is_a?(Hash) - options ||= {} - - case record - when String, Symbol - object = record_object - object_name = record - else - object = record - object_name = ActiveModel::Naming.param_key(object) - end - - builder = options[:builder] || ActionView::Base.default_form_builder - capture(builder.new(object_name, object, self, options, block), &block) + capture(instantiate_builder(record, record_object, options, &block), &block) end # Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object @@ -848,6 +836,27 @@ module ActionView def range_field(object_name, method, options = {}) InstanceTag.new(object_name, method, self, options.delete(:object)).to_number_field_tag("range", options) end + + private + + def instantiate_builder(record, record_object = nil, options = nil, &block) + raise ArgumentError, "Missing block" unless block_given? + + options, record_object = record_object, nil if record_object.is_a?(Hash) + options ||= {} + + case record + when String, Symbol + object = record_object + object_name = record + else + object = record + object_name = ActiveModel::Naming.param_key(object) + end + + builder = options[:builder] || ActionView::Base.default_form_builder + builder.new(object_name, object, self, options, block) + end end module InstanceTagMethods #:nodoc: @@ -1112,6 +1121,9 @@ module ActionView attr_accessor :object_name, :object, :options + attr_reader :multipart + alias :multipart? :multipart + def self.model_name @model_name ||= Struct.new(:partial_path).new(name.demodulize.underscore.sub!(/_builder$/, '')) end @@ -1131,9 +1143,10 @@ module ActionView raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}" end end + @multipart = nil end - (field_helpers - %w(label check_box radio_button fields_for hidden_field)).each do |selector| + (field_helpers - %w(label check_box radio_button fields_for hidden_field file_field)).each do |selector| class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{selector}(method, options = {}) # def text_field(method, options = {}) @template.send( # @template.send( @@ -1197,6 +1210,10 @@ module ActionView @template.hidden_field(@object_name, method, objectify_options(options)) end + def file_field(method, options = {}) + @multipart = true + @template.file_field(@object_name, method, objectify_options(options)) + end # Add the submit button for the given form. When no value is given, it checks # if the object is a new resource or not to create the proper label: # diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb index 97a08d45ba..348aa208c7 100644 --- a/actionpack/test/template/form_helper_test.rb +++ b/actionpack/test/template/form_helper_test.rb @@ -665,6 +665,24 @@ class FormHelperTest < ActionView::TestCase assert_dom_equal expected, output_buffer end + def test_form_for_with_file_field_generate_multipart + Post.send :attr_accessor, :file + + assert_deprecated do + form_for(:post, @post, :html => { :id => 'create-post' }) do |f| + concat f.file_field(:file) + end + end + + expected = + "
" + + snowman + + "" + + "
" + + assert_dom_equal expected, output_buffer + end + def test_form_for_with_format form_for(@post, :format => :json, :html => { :id => "edit_post_123", :class => "edit_post" }) do |f| concat f.label(:title) -- cgit v1.2.3