Skip to content
This repository
Browse code

Fix several known web encoding issues:

* Specify accept-charset on all forms. All recent browsers,
  as well as IE5+, will use the encoding specified for form
  parameters
* Unfortunately, IE5+ will not look at accept-charset unless
  at least one character in the form's values is not in the
  page's charset. Since the user can override the default
  charset (which Rails sets to UTF-8), we provide a hidden
  input containing a unicode character, forcing IE to look
  at the accept-charset.
* Now that the vast majority of web input is UTF-8, we set
  the inbound parameters to UTF-8. This will eliminate many
  cases of incompatible encodings between ASCII-8BIT and
  UTF-8.
* You can safely ignore params[:_snowman_]

TODO:

* Validate inbound text to confirm it is UTF-8
* Combine the whole_form implementations in form_helper_test
  and form_tag_helper_test
  • Loading branch information...
commit 25215d7285db10e2c04d903f251b791342e4dd6a 1 parent 06b0d6e
Yehuda Katz authored June 27, 2010
31  actionpack/lib/action_dispatch/http/parameters.rb
@@ -6,7 +6,11 @@ module Http
6 6
     module Parameters
7 7
       # Returns both GET and POST \parameters in a single hash.
8 8
       def parameters
9  
-        @env["action_dispatch.request.parameters"] ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
  9
+        @env["action_dispatch.request.parameters"] ||= begin
  10
+          params = request_parameters.merge(query_parameters)
  11
+          params.merge!(path_parameters)
  12
+          encode_params(params).with_indifferent_access
  13
+        end
10 14
       end
11 15
       alias :params :parameters
12 16
 
@@ -32,6 +36,31 @@ def path_parameters
32 36
       end
33 37
 
34 38
     private
  39
+
  40
+      # TODO: Validate that the characters are UTF-8. If they aren't,
  41
+      # you'll get a weird error down the road, but our form handling
  42
+      # should really prevent that from happening
  43
+      def encode_params(params)
  44
+        return params unless "ruby".encoding_aware?
  45
+
  46
+        if params.is_a?(String)
  47
+          return params.force_encoding("UTF-8").encode!
  48
+        elsif !params.is_a?(Hash)
  49
+          return params
  50
+        end
  51
+
  52
+        params.each do |k, v|
  53
+          case v
  54
+          when Hash
  55
+            encode_params(v)
  56
+          when Array
  57
+            v.map! {|el| encode_params(el) }
  58
+          else
  59
+            encode_params(v)
  60
+          end
  61
+        end
  62
+      end
  63
+
35 64
       # Convert nested Hash to HashWithIndifferentAccess
36 65
       def normalize_parameters(value)
37 66
         case value
15  actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -530,22 +530,31 @@ def html_options_for_form(url_for_options, options, *parameters_for_url)
530 530
           returning options.stringify_keys do |html_options|
531 531
             html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
532 532
             html_options["action"]  = url_for(url_for_options, *parameters_for_url)
  533
+            html_options["accept-encoding"] = "UTF-8"
533 534
             html_options["data-remote"] = true if html_options.delete("remote")
534 535
           end
535 536
         end
536 537
 
537 538
         def extra_tags_for_form(html_options)
538  
-          case method = html_options.delete("method").to_s
  539
+          snowman_tag = tag(:input, :type => "hidden",
  540
+                            :name => "_snowman_", :value => "☃")
  541
+
  542
+          method = html_options.delete("method").to_s
  543
+
  544
+          method_tag = case method
539 545
             when /^get$/i # must be case-insensitive, but can't use downcase as might be nil
540 546
               html_options["method"] = "get"
541 547
               ''
542 548
             when /^post$/i, "", nil
543 549
               html_options["method"] = "post"
544  
-              protect_against_forgery? ? content_tag(:div, token_tag, :style => 'margin:0;padding:0;display:inline') : ''
  550
+              token_tag
545 551
             else
546 552
               html_options["method"] = "post"
547  
-              content_tag(:div, tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag, :style => 'margin:0;padding:0;display:inline')
  553
+              tag(:input, :type => "hidden", :name => "_method", :value => method) + token_tag
548 554
           end
  555
+
  556
+          tags = snowman_tag << method_tag
  557
+          content_tag(:div, tags, :style => 'margin:0;padding:0;display:inline')
549 558
         end
550 559
 
551 560
         def form_tag_html(html_options)
23  actionpack/test/dispatch/request/url_encoded_params_parsing_test.rb
@@ -141,6 +141,29 @@ def assert_parses(expected, actual)
141 141
         post "/parse", actual
142 142
         assert_response :ok
143 143
         assert_equal(expected, TestController.last_request_parameters)
  144
+        assert_utf8(TestController.last_request_parameters)
  145
+      end
  146
+    end
  147
+
  148
+    def assert_utf8(object)
  149
+      return unless "ruby".encoding_aware?
  150
+
  151
+      correct_encoding = Encoding.default_internal
  152
+
  153
+      unless object.is_a?(Hash)
  154
+        assert_equal correct_encoding, object.encoding, "#{object.inspect} should have been UTF-8"
  155
+        return
  156
+      end
  157
+
  158
+      object.each do |k,v|
  159
+        case v
  160
+        when Hash
  161
+          assert_utf8(v)
  162
+        when Array
  163
+          v.each {|el| assert_utf8(el) }
  164
+        else
  165
+          assert_utf8(v)
  166
+        end
144 167
       end
145 168
     end
146 169
 end
2  actionpack/test/template/erb/form_for_test.rb
@@ -5,7 +5,7 @@ module ERBTest
5 5
   class TagHelperTest < BlockTestCase
6 6
     test "form_for works" do
7 7
       output = render_content "form_for(:staticpage, :url => {:controller => 'blah', :action => 'update'})", ""
8  
-      assert_equal "<form action=\"/blah/update\" method=\"post\"></form>", output
  8
+      assert_match %r{<form.*action="/blah/update".*method="post">.*</form>}, output
9 9
     end
10 10
   end
11 11
 end
4  actionpack/test/template/erb/tag_helper_test.rb
@@ -28,8 +28,8 @@ def maybe_deprecated
28 28
     end
29 29
 
30 30
     test "percent equals works with form tags" do
31  
-      expected_output = "<form action=\"foo\" method=\"post\">hello</form>"
32  
-      maybe_deprecated { assert_equal expected_output, render_content("form_tag('foo')", "<%= 'hello' %>") }
  31
+      expected_output = %r{<form.*action="foo".*method="post">.*hello*</form>}
  32
+      maybe_deprecated { assert_match expected_output, render_content("form_tag('foo')", "<%= 'hello' %>") }
33 33
     end
34 34
 
35 35
     test "percent equals works with fieldset tags" do
385  actionpack/test/template/form_helper_test.rb
@@ -583,7 +583,8 @@ def test_form_for
583 583
     end
584 584
 
585 585
     expected =
586  
-      "<form action='http://www.example.com' id='create-post' method='post'>" +
  586
+      "<form accept-charset='UTF-8' action='http://www.example.com' id='create-post' method='post'>" +
  587
+      snowman +
587 588
       "<label for='post_title'>The Title</label>" +
588 589
       "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
589 590
       "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
@@ -604,15 +605,14 @@ def test_form_for_with_symbol_object_name
604 605
       concat f.submit('Create post')
605 606
     end
606 607
 
607  
-    expected =
608  
-      "<form class='other_name_edit' method='post' action='/posts/123' id='create-post'>" +
609  
-      "<div style='margin:0;padding:0;display:inline'><input name='_method' value='put' type='hidden' /></div>" +
  608
+    expected =  whole_form("/posts/123", "create-post", "other_name_edit", :method => "put") do
610 609
       "<label for='other_name_title'>Title</label>" +
611 610
       "<input name='other_name[title]' size='30' id='other_name_title' value='Hello World' type='text' />" +
612 611
       "<textarea name='other_name[body]' id='other_name_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
613 612
       "<input name='other_name[secret]' value='0' type='hidden' />" +
614 613
       "<input name='other_name[secret]' checked='checked' id='other_name_secret' value='1' type='checkbox' />" +
615  
-      "<input name='commit' id='other_name_submit' value='Create post' type='submit' /></form>"
  614
+      "<input name='commit' id='other_name_submit' value='Create post' type='submit' />"
  615
+    end
616 616
 
617 617
     assert_dom_equal expected, output_buffer
618 618
   end
@@ -626,14 +626,12 @@ def test_form_for_with_method
626 626
       end
627 627
     end
628 628
 
629  
-    expected =
630  
-      "<form action='http://www.example.com' id='create-post' method='post'>" +
631  
-      "<div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>" +
  629
+    expected =  whole_form("http://www.example.com", "create-post", nil, "put") do
632 630
       "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
633 631
       "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
634 632
       "<input name='post[secret]' type='hidden' value='0' />" +
635  
-      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
636  
-      "</form>"
  633
+      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />"
  634
+    end
637 635
 
638 636
     assert_dom_equal expected, output_buffer
639 637
   end
@@ -647,14 +645,12 @@ def test_form_for_with_remote
647 645
       end
648 646
     end
649 647
 
650  
-    expected =
651  
-      "<form action='http://www.example.com' id='create-post' method='post' data-remote='true'>" +
652  
-      "<div style='margin:0;padding:0;display:inline'><input name='_method' type='hidden' value='put' /></div>" +
  648
+    expected =  whole_form("http://www.example.com", "create-post", nil, :method => "put", :remote => true) do
653 649
       "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
654 650
       "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
655 651
       "<input name='post[secret]' type='hidden' value='0' />" +
656  
-      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
657  
-      "</form>"
  652
+      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />"
  653
+    end
658 654
 
659 655
     assert_dom_equal expected, output_buffer
660 656
   end
@@ -668,13 +664,12 @@ def test_form_for_with_remote_without_html
668 664
       end
669 665
     end
670 666
 
671  
-    expected =
672  
-      "<form action='http://www.example.com' method='post' data-remote='true'>" +
  667
+    expected =  whole_form("http://www.example.com", nil, nil, :remote => true) do
673 668
       "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
674 669
       "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
675 670
       "<input name='post[secret]' type='hidden' value='0' />" +
676  
-      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
677  
-      "</form>"
  671
+      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />"
  672
+    end
678 673
 
679 674
     assert_dom_equal expected, output_buffer
680 675
   end
@@ -686,13 +681,12 @@ def test_form_for_without_object
686 681
       concat f.check_box(:secret)
687 682
     end
688 683
 
689  
-    expected =
690  
-      "<form action='http://www.example.com' id='create-post' method='post'>" +
  684
+    expected =  whole_form("http://www.example.com", "create-post") do
691 685
       "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
692 686
       "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
693 687
       "<input name='post[secret]' type='hidden' value='0' />" +
694  
-      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />" +
695  
-      "</form>"
  688
+      "<input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' />"
  689
+    end
696 690
 
697 691
     assert_dom_equal expected, output_buffer
698 692
   end
@@ -707,14 +701,13 @@ def test_form_for_with_index
707 701
       end
708 702
     end
709 703
 
710  
-    expected =
711  
-      "<form action='http://www.example.com' method='post'>" +
  704
+    expected = whole_form do
712 705
       "<label for='post_123_title'>Title</label>" +
713 706
       "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" +
714 707
       "<textarea name='post[123][body]' id='post_123_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
715 708
       "<input name='post[123][secret]' type='hidden' value='0' />" +
716  
-      "<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />" +
717  
-      "</form>"
  709
+      "<input name='post[123][secret]' checked='checked' type='checkbox' id='post_123_secret' value='1' />"
  710
+    end
718 711
 
719 712
     assert_dom_equal expected, output_buffer
720 713
   end
@@ -728,13 +721,12 @@ def test_form_for_with_nil_index_option_override
728 721
       end
729 722
     end
730 723
 
731  
-    expected =
732  
-      "<form action='http://www.example.com' method='post'>" +
  724
+    expected = whole_form do
733 725
       "<input name='post[][title]' size='30' type='text' id='post__title' value='Hello World' />" +
734 726
       "<textarea name='post[][body]' id='post__body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
735 727
       "<input name='post[][secret]' type='hidden' value='0' />" +
736  
-      "<input name='post[][secret]' checked='checked' type='checkbox' id='post__secret' value='1' />" +
737  
-      "</form>"
  728
+      "<input name='post[][secret]' checked='checked' type='checkbox' id='post__secret' value='1' />"
  729
+    end
738 730
 
739 731
     assert_dom_equal expected, output_buffer
740 732
   end
@@ -749,9 +741,10 @@ def test_submit_with_object_as_new_record_and_locale_strings
749 741
       end
750 742
     end
751 743
 
752  
-    expected = "<form action='http://www.example.com' method='post'>" +
753  
-               "<input name='commit' id='post_submit' type='submit' value='Create Post' />" +
754  
-               "</form>"
  744
+    expected =  whole_form do
  745
+                  "<input name='commit' id='post_submit' type='submit' value='Create Post' />"
  746
+                end
  747
+
755 748
     assert_dom_equal expected, output_buffer
756 749
   ensure
757 750
     I18n.locale = old_locale
@@ -766,9 +759,10 @@ def test_submit_with_object_as_existing_record_and_locale_strings
766 759
       end
767 760
     end
768 761
 
769  
-    expected = "<form action='http://www.example.com' method='post'>" +
770  
-               "<input name='commit' id='post_submit' type='submit' value='Confirm Post changes' />" +
771  
-               "</form>"
  762
+    expected =  whole_form do
  763
+                  "<input name='commit' id='post_submit' type='submit' value='Confirm Post changes' />"
  764
+                end
  765
+
772 766
     assert_dom_equal expected, output_buffer
773 767
   ensure
774 768
     I18n.locale = old_locale
@@ -781,9 +775,10 @@ def test_submit_without_object_and_locale_strings
781 775
       concat f.submit :class => "extra"
782 776
     end
783 777
 
784  
-    expected = "<form action='http://www.example.com' method='post'>" +
785  
-               "<input name='commit' class='extra' id='post_submit' type='submit' value='Save changes' />" +
786  
-               "</form>"
  778
+    expected =  whole_form do
  779
+                  "<input name='commit' class='extra' id='post_submit' type='submit' value='Save changes' />"
  780
+                end
  781
+
787 782
     assert_dom_equal expected, output_buffer
788 783
   ensure
789 784
     I18n.locale = old_locale
@@ -798,9 +793,10 @@ def test_submit_with_object_and_nested_lookup
798 793
       end
799 794
     end
800 795
 
801  
-    expected = "<form action='http://www.example.com' method='post'>" +
802  
-               "<input name='commit' id='another_post_submit' type='submit' value='Update your Post' />" +
803  
-               "</form>"
  796
+    expected =  whole_form do
  797
+                  "<input name='commit' id='another_post_submit' type='submit' value='Update your Post' />"
  798
+                end
  799
+
804 800
     assert_dom_equal expected, output_buffer
805 801
   ensure
806 802
     I18n.locale = old_locale
@@ -815,9 +811,9 @@ def test_nested_fields_for
815 811
       end
816 812
     end
817 813
 
818  
-    expected = "<form action='http://www.example.com' method='post'>" +
819  
-               "<input name='post[comment][title]' size='30' type='text' id='post_comment_title' value='Hello World' />" +
820  
-               "</form>"
  814
+    expected =  whole_form do
  815
+                  "<input name='post[comment][title]' size='30' type='text' id='post_comment_title' value='Hello World' />"
  816
+                end
821 817
 
822 818
     assert_dom_equal expected, output_buffer
823 819
   end
@@ -832,10 +828,10 @@ def test_nested_fields_for_with_nested_collections
832 828
       end
833 829
     end
834 830
 
835  
-    expected = "<form action='http://www.example.com' method='post'>" +
836  
-               "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" +
837  
-               "<input name='post[123][comment][][name]' size='30' type='text' id='post_123_comment__name' value='new comment' />" +
838  
-               "</form>"
  831
+    expected =  whole_form do
  832
+                  "<input name='post[123][title]' size='30' type='text' id='post_123_title' value='Hello World' />" +
  833
+                  "<input name='post[123][comment][][name]' size='30' type='text' id='post_123_comment__name' value='new comment' />"
  834
+                end
839 835
 
840 836
     assert_dom_equal expected, output_buffer
841 837
   end
@@ -850,10 +846,10 @@ def test_nested_fields_for_with_index_and_parent_fields
850 846
       end
851 847
     end
852 848
 
853  
-    expected = "<form action='http://www.example.com' method='post'>" +
854  
-               "<input name='post[1][title]' size='30' type='text' id='post_1_title' value='Hello World' />" +
855  
-               "<input name='post[1][comment][1][name]' size='30' type='text' id='post_1_comment_1_name' value='new comment' />" +
856  
-               "</form>"
  849
+    expected =  whole_form do
  850
+                  "<input name='post[1][title]' size='30' type='text' id='post_1_title' value='Hello World' />" +
  851
+                  "<input name='post[1][comment][1][name]' size='30' type='text' id='post_1_comment_1_name' value='new comment' />"
  852
+                end
857 853
 
858 854
     assert_dom_equal expected, output_buffer
859 855
   end
@@ -867,9 +863,9 @@ def test_form_for_with_index_and_nested_fields_for
867 863
       end
868 864
     end
869 865
 
870  
-    expected = "<form action='http://www.example.com' method='post'>" +
871  
-               "<input name='post[1][comment][title]' size='30' type='text' id='post_1_comment_title' value='Hello World' />" +
872  
-               "</form>"
  866
+    expected =  whole_form do
  867
+                  "<input name='post[1][comment][title]' size='30' type='text' id='post_1_comment_title' value='Hello World' />"
  868
+                end
873 869
 
874 870
     assert_dom_equal expected, output_buffer
875 871
   end
@@ -883,9 +879,9 @@ def test_nested_fields_for_with_index_on_both
883 879
       end
884 880
     end
885 881
 
886  
-    expected = "<form action='http://www.example.com' method='post'>" +
887  
-               "<input name='post[1][comment][5][title]' size='30' type='text' id='post_1_comment_5_title' value='Hello World' />" +
888  
-               "</form>"
  882
+    expected =  whole_form do
  883
+                  "<input name='post[1][comment][5][title]' size='30' type='text' id='post_1_comment_5_title' value='Hello World' />"
  884
+                end
889 885
 
890 886
     assert_dom_equal expected, output_buffer
891 887
   end
@@ -899,9 +895,9 @@ def test_nested_fields_for_with_auto_index
899 895
       end
900 896
     end
901 897
 
902  
-    expected = "<form action='http://www.example.com' method='post'>" +
903  
-               "<input name='post[123][comment][title]' size='30' type='text' id='post_123_comment_title' value='Hello World' />" +
904  
-               "</form>"
  898
+    expected =  whole_form do
  899
+                  "<input name='post[123][comment][title]' size='30' type='text' id='post_123_comment_title' value='Hello World' />"
  900
+                end
905 901
 
906 902
     assert_dom_equal expected, output_buffer
907 903
   end
@@ -915,9 +911,9 @@ def test_nested_fields_for_with_index_radio_button
915 911
       end
916 912
     end
917 913
 
918  
-    expected = "<form action='http://www.example.com' method='post'>" +
919  
-               "<input name='post[comment][5][title]' type='radio' id='post_comment_5_title_hello' value='hello' />" +
920  
-               "</form>"
  914
+    expected =  whole_form do
  915
+                  "<input name='post[comment][5][title]' type='radio' id='post_comment_5_title_hello' value='hello' />"
  916
+                end
921 917
 
922 918
     assert_dom_equal expected, output_buffer
923 919
   end
@@ -931,9 +927,9 @@ def test_nested_fields_for_with_auto_index_on_both
931 927
       end
932 928
     end
933 929
 
934  
-    expected = "<form action='http://www.example.com' method='post'>" +
935  
-               "<input name='post[123][comment][123][title]' size='30' type='text' id='post_123_comment_123_title' value='Hello World' />" +
936  
-               "</form>"
  930
+    expected =  whole_form do
  931
+                  "<input name='post[123][comment][123][title]' size='30' type='text' id='post_123_comment_123_title' value='Hello World' />"
  932
+                end
937 933
 
938 934
     assert_dom_equal expected, output_buffer
939 935
   end
@@ -952,12 +948,11 @@ def test_nested_fields_for_with_index_and_auto_index
952 948
         }
953 949
       end
954 950
 
955  
-      expected = "<form action='http://www.example.com' method='post'>" +
956  
-                 "<input name='post[123][comment][5][title]' size='30' type='text' id='post_123_comment_5_title' value='Hello World' />" +
957  
-                 "</form>" +
958  
-                 "<form action='http://www.example.com' method='post'>" +
959  
-                 "<input name='post[1][comment][123][title]' size='30' type='text' id='post_1_comment_123_title' value='Hello World' />" +
960  
-                 "</form>"
  951
+      expected =  whole_form do
  952
+                    "<input name='post[123][comment][5][title]' size='30' type='text' id='post_123_comment_5_title' value='Hello World' />"
  953
+                  end + whole_form do
  954
+                    "<input name='post[1][comment][123][title]' size='30' type='text' id='post_1_comment_123_title' value='Hello World' />"
  955
+                  end
961 956
 
962 957
       assert_dom_equal expected, output_buffer
963 958
     end
@@ -975,10 +970,10 @@ def test_nested_fields_for_with_a_new_record_on_a_nested_attributes_one_to_one_a
975 970
       end
976 971
     end
977 972
 
978  
-    expected = '<form action="http://www.example.com" method="post">' +
979  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
980  
-               '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="new author" />' +
981  
-               '</form>'
  973
+    expected =  whole_form do
  974
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  975
+                  '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="new author" />'
  976
+                end
982 977
 
983 978
     assert_dom_equal expected, output_buffer
984 979
   end
@@ -1006,11 +1001,11 @@ def test_nested_fields_for_with_an_existing_record_on_a_nested_attributes_one_to
1006 1001
       end
1007 1002
     end
1008 1003
 
1009  
-    expected = '<form action="http://www.example.com" method="post">' +
1010  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1011  
-               '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' +
1012  
-               '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
1013  
-               '</form>'
  1004
+    expected =  whole_form do
  1005
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1006
+                  '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' +
  1007
+                  '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />'
  1008
+                end
1014 1009
 
1015 1010
     assert_dom_equal expected, output_buffer
1016 1011
   end
@@ -1028,11 +1023,11 @@ def test_nested_fields_for_with_existing_records_on_a_nested_attributes_one_to_o
1028 1023
       end
1029 1024
     end
1030 1025
 
1031  
-    expected = '<form action="http://www.example.com" method="post">' +
1032  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1033  
-               '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
1034  
-               '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' +
1035  
-               '</form>'
  1026
+    expected =  whole_form do
  1027
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1028
+                  '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
  1029
+                  '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />'
  1030
+                end
1036 1031
 
1037 1032
     assert_dom_equal expected, output_buffer
1038 1033
   end
@@ -1051,13 +1046,13 @@ def test_nested_fields_for_with_existing_records_on_a_nested_attributes_collecti
1051 1046
       end
1052 1047
     end
1053 1048
 
1054  
-    expected = '<form action="http://www.example.com" method="post">' +
1055  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1056  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
1057  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
1058  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
1059  
-               '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
1060  
-               '</form>'
  1049
+    expected =  whole_form do
  1050
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1051
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
  1052
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
  1053
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
  1054
+                  '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />'
  1055
+                end
1061 1056
 
1062 1057
     assert_dom_equal expected, output_buffer
1063 1058
   end
@@ -1077,13 +1072,13 @@ def test_nested_fields_for_with_existing_records_on_a_nested_attributes_collecti
1077 1072
       end
1078 1073
     end
1079 1074
 
1080  
-    expected = '<form action="http://www.example.com" method="post">' +
1081  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1082  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
1083  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
1084  
-               '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
1085  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
1086  
-               '</form>'
  1075
+    expected =  whole_form do
  1076
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1077
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
  1078
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
  1079
+                  '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
  1080
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />'
  1081
+                end
1087 1082
 
1088 1083
     assert_dom_equal expected, output_buffer
1089 1084
   end
@@ -1102,11 +1097,11 @@ def test_nested_fields_for_with_new_records_on_a_nested_attributes_collection_as
1102 1097
       end
1103 1098
     end
1104 1099
 
1105  
-    expected = '<form action="http://www.example.com" method="post">' +
1106  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1107  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="new comment" />' +
1108  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
1109  
-               '</form>'
  1100
+    expected =  whole_form do
  1101
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1102
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="new comment" />' +
  1103
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />'
  1104
+                end
1110 1105
 
1111 1106
     assert_dom_equal expected, output_buffer
1112 1107
   end
@@ -1125,12 +1120,12 @@ def test_nested_fields_for_with_existing_and_new_records_on_a_nested_attributes_
1125 1120
       end
1126 1121
     end
1127 1122
 
1128  
-    expected = '<form action="http://www.example.com" method="post">' +
1129  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1130  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
1131  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
1132  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
1133  
-               '</form>'
  1123
+    expected =  whole_form do
  1124
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1125
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
  1126
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
  1127
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />'
  1128
+                end
1134 1129
 
1135 1130
     assert_dom_equal expected, output_buffer
1136 1131
   end
@@ -1145,9 +1140,9 @@ def test_nested_fields_for_with_an_empty_supplied_attributes_collection
1145 1140
       end
1146 1141
     end
1147 1142
 
1148  
-    expected = '<form action="http://www.example.com" method="post">' +
1149  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1150  
-               '</form>'
  1143
+    expected =  whole_form do
  1144
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />'
  1145
+                end
1151 1146
 
1152 1147
     assert_dom_equal expected, output_buffer
1153 1148
   end
@@ -1164,13 +1159,13 @@ def test_nested_fields_for_with_existing_records_on_a_supplied_nested_attributes
1164 1159
       end
1165 1160
     end
1166 1161
 
1167  
-    expected = '<form action="http://www.example.com" method="post">' +
1168  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1169  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
1170  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
1171  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
1172  
-               '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
1173  
-               '</form>'
  1162
+    expected =  whole_form do
  1163
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1164
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
  1165
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
  1166
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
  1167
+                  '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />'
  1168
+                end
1174 1169
 
1175 1170
     assert_dom_equal expected, output_buffer
1176 1171
   end
@@ -1188,13 +1183,13 @@ def test_nested_fields_for_with_existing_records_on_a_supplied_nested_attributes
1188 1183
       end
1189 1184
     end
1190 1185
 
1191  
-    expected = '<form action="http://www.example.com" method="post">' +
1192  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1193  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
1194  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
1195  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
1196  
-               '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
1197  
-               '</form>'
  1186
+    expected =  whole_form do
  1187
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1188
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
  1189
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
  1190
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
  1191
+                  '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />'
  1192
+                end
1198 1193
 
1199 1194
     assert_dom_equal expected, output_buffer
1200 1195
   end
@@ -1213,12 +1208,12 @@ def test_nested_fields_for_on_a_nested_attributes_collection_association_yields_
1213 1208
       end
1214 1209
     end
1215 1210
 
1216  
-    expected = '<form action="http://www.example.com" method="post">' +
1217  
-               '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
1218  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
1219  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
1220  
-               '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
1221  
-               '</form>'
  1211
+    expected =  whole_form do
  1212
+                  '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
  1213
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
  1214
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
  1215
+                  '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />'
  1216
+                end
1222 1217
 
1223 1218
     assert_dom_equal expected, output_buffer
1224 1219
     assert_equal yielded_comments, @post.comments
@@ -1235,10 +1230,10 @@ def test_nested_fields_for_with_child_index_option_override_on_a_nested_attribut
1235 1230
       end
1236 1231
     end
1237 1232
 
1238  
-    expected = '<form action="http://www.example.com" method="post">' +
1239  
-               '<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" size="30" type="text" value="comment #321" />' +
1240  
-               '<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' +
1241  
-               '</form>'
  1233
+    expected =  whole_form do
  1234
+                  '<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" size="30" type="text" value="comment #321" />' +
  1235
+                  '<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />'
  1236
+                end
1242 1237
 
1243 1238
     assert_dom_equal expected, output_buffer
1244 1239
   end
@@ -1273,20 +1268,20 @@ def test_nested_fields_uses_unique_indices_for_different_collection_associations
1273 1268
       end
1274 1269
     end
1275 1270
 
1276  
-    expected = '<form action="http://www.example.com" method="post">' +
1277  
-               '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
1278  
-               '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' +
1279  
-               '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
1280  
-               '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
1281  
-               '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' +
1282  
-               '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' +
1283  
-               '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
1284  
-               '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
1285  
-               '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' +
1286  
-               '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' +
1287  
-               '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
1288  
-               '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' +
1289  
-               '</form>'
  1271
+    expected =  whole_form do
  1272
+                  '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
  1273
+                  '<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' +
  1274
+                  '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
  1275
+                  '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
  1276
+                  '<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' +
  1277
+                  '<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' +
  1278
+                  '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
  1279
+                  '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
  1280
+                  '<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' +
  1281
+                  '<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' +
  1282
+                  '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
  1283
+                  '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />'
  1284
+                end
1290 1285
 
1291 1286
     assert_dom_equal expected, output_buffer
1292 1287
   end
@@ -1426,7 +1421,8 @@ def test_form_for_and_fields_for
1426 1421
     end
1427 1422
 
1428 1423
     expected =
1429  
-      "<form action='http://www.example.com' id='create-post' method='post'>" +
  1424
+      "<form accept-charset='UTF-8' action='http://www.example.com' id='create-post' method='post'>" +
  1425
+      snowman +
1430 1426
       "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
1431 1427
       "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
1432 1428
       "<input name='parent_post[secret]' type='hidden' value='0' />" +
@@ -1449,11 +1445,11 @@ def test_form_for_and_fields_for_with_object
1449 1445
     end
1450 1446
 
1451 1447
     expected =
1452  
-      "<form action='http://www.example.com' id='create-post' method='post'>" +
1453  
-      "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
1454  
-      "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
1455  
-      "<input name='post[comment][name]' type='text' id='post_comment_name' value='new comment' size='30' />" +
1456  
-      "</form>"
  1448
+      whole_form("http://www.example.com", "create-post") do
  1449
+        "<input name='post[title]' size='30' type='text' id='post_title' value='Hello World' />" +
  1450
+        "<textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
  1451
+        "<input name='post[comment][name]' type='text' id='post_comment_name' value='new comment' size='30' />"
  1452
+      end
1457 1453
 
1458 1454
     assert_dom_equal expected, output_buffer
1459 1455
   end
@@ -1477,16 +1473,42 @@ def test_form_for_with_labelled_builder
1477 1473
       end
1478 1474
     end
1479 1475
 
1480  
-    expected =
1481  
-      "<form action='http://www.example.com' method='post'>" +
1482  
-      "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
1483  
-      "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
1484  
-      "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" +
1485  
-      "</form>"
  1476
+    expected =  whole_form do
  1477
+        "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
  1478
+        "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
  1479
+        "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>"
  1480
+      end
1486 1481
 
1487 1482
     assert_dom_equal expected, output_buffer
1488 1483
   end
1489 1484
 
  1485
+  def snowman(method = nil)
  1486
+    txt =  %{<div style="margin:0;padding:0;display:inline">}
  1487
+    txt << %{<input name="_snowman_" type="hidden" value="&#9731;" />}
  1488
+    txt << %{<input name="_method" type="hidden" value="#{method}" />} if method
  1489
+    txt << %{</div>}
  1490
+  end
  1491
+
  1492
+  def form_text(action = "http://www.example.com", id = nil, html_class = nil, remote = nil)
  1493
+    txt =  %{<form accept-charset="UTF-8" action="#{action}"}
  1494
+    txt << %{ data-remote="true"} if remote
  1495
+    txt << %{ class="#{html_class}"} if html_class
  1496
+    txt << %{ id="#{id}"} if id
  1497
+    txt << %{ method="post">}
  1498
+  end
  1499
+
  1500
+  def whole_form(action = "http://www.example.com", id = nil, html_class = nil, options = nil)
  1501
+    contents = block_given? ? yield : ""
  1502
+
  1503
+    if options.is_a?(Hash)
  1504
+      method, remote = options.values_at(:method, :remote)
  1505
+    else
  1506
+      method = options
  1507
+    end
  1508
+
  1509
+    form_text(action, id, html_class, remote) + snowman(method) + contents + "</form>"
  1510
+  end
  1511
+
1490 1512
   def test_default_form_builder
1491 1513
     old_default_form_builder, ActionView::Base.default_form_builder =
1492 1514
       ActionView::Base.default_form_builder, LabelledFormBuilder
@@ -1499,12 +1521,11 @@ def test_default_form_builder
1499 1521
       end
1500 1522
     end
1501 1523
 
1502  
-    expected =
1503  
-      "<form action='http://www.example.com' method='post'>" +
  1524
+    expected =  whole_form do
1504 1525
       "<label for='title'>Title:</label> <input name='post[title]' size='30' type='text' id='post_title' value='Hello World' /><br/>" +
1505 1526
       "<label for='body'>Body:</label> <textarea name='post[body]' id='post_body' rows='20' cols='40'>Back to the hill and over it again!</textarea><br/>" +
1506  
-      "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>" +
1507  
-      "</form>"
  1527
+      "<label for='secret'>Secret:</label> <input name='post[secret]' type='hidden' value='0' /><input name='post[secret]' checked='checked' type='checkbox' id='post_secret' value='1' /><br/>"
  1528
+    end
1508 1529
 
1509 1530
     assert_dom_equal expected, output_buffer
1510 1531
   ensure
@@ -1577,7 +1598,7 @@ def test_form_for_with_html_options_adds_options_to_form_tag
1577 1598
     assert_deprecated do
1578 1599
       form_for(:post, @post, :html => {:id => 'some_form', :class => 'some_class'}) do |f| end
1579 1600
     end
1580  
-    expected = "<form action=\"http://www.example.com\" class=\"some_class\" id=\"some_form\" method=\"post\"></form>"
  1601
+    expected = whole_form("http://www.example.com", "some_form", "some_class")
1581 1602
 
1582 1603
     assert_dom_equal expected, output_buffer
1583 1604
   end
@@ -1587,7 +1608,8 @@ def test_form_for_with_string_url_option
1587 1608
       form_for(:post, @post, :url => 'http://www.otherdomain.com') do |f| end
1588 1609
     end
1589 1610
 
1590  
-    assert_equal '<form action="http://www.otherdomain.com" method="post"></form>', output_buffer
  1611
+    assert_equal whole_form("http://www.otherdomain.com"), output_buffer
  1612
+    # assert_equal '<form action="http://www.otherdomain.com" method="post"></form>', output_buffer
1591 1613
   end
1592 1614
 
1593 1615
   def test_form_for_with_hash_url_option
@@ -1604,14 +1626,15 @@ def test_form_for_with_record_url_option
1604 1626
       form_for(:post, @post, :url => @post) do |f| end
1605 1627
     end
1606 1628
 
1607  
-    expected = "<form action=\"/posts/123\" method=\"post\"></form>"
  1629
+    expected = whole_form("/posts/123")
  1630
+    # expected = "<form action=\"/posts/123\" method=\"post\"></form>"
1608 1631
     assert_equal expected, output_buffer
1609 1632
   end
1610 1633
 
1611 1634
   def test_form_for_with_existing_object
1612 1635
     form_for(@post) do |f| end
1613 1636
 
1614  
-    expected = "<form action=\"/posts/123\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
  1637
+    expected = whole_form("/posts/123", "edit_post_123", "edit_post", "put")
1615 1638
     assert_equal expected, output_buffer
1616 1639
   end
1617 1640
 
@@ -1622,7 +1645,7 @@ def post.id() nil end
1622 1645
 
1623 1646
     form_for(post) do |f| end
1624 1647
 
1625  
-    expected = "<form action=\"/posts\" class=\"new_post\" id=\"new_post\" method=\"post\"></form>"
  1648
+    expected = whole_form("/posts", "new_post", "new_post")
1626 1649
     assert_equal expected, output_buffer
1627 1650
   end
1628 1651
 
@@ -1630,14 +1653,14 @@ def test_form_for_with_existing_object_in_list
1630 1653
     @comment.save
1631 1654
     form_for([@post, @comment]) {}
1632 1655
 
1633  
-    expected = %(<form action="#{comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0;display:inline"><input name="_method" type="hidden" value="put" /></div></form>)
  1656
+    expected = whole_form(comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put")
1634 1657
     assert_dom_equal expected, output_buffer
1635 1658
   end
1636 1659
 
1637 1660
   def test_form_for_with_new_object_in_list
1638 1661
     form_for([@post, @comment]) {}
1639 1662
 
1640  
-    expected = %(<form action="#{comments_path(@post)}" class="new_comment" id="new_comment" method="post"></form>)
  1663
+    expected = whole_form(comments_path(@post), "new_comment", "new_comment")
1641 1664
     assert_dom_equal expected, output_buffer
1642 1665
   end
1643 1666
 
@@ -1645,21 +1668,21 @@ def test_form_for_with_existing_object_and_namespace_in_list
1645 1668
     @comment.save
1646 1669
     form_for([:admin, @post, @comment]) {}
1647 1670
 
1648  
-    expected = %(<form action="#{admin_comment_path(@post, @comment)}" class="edit_comment" id="edit_comment_1" method="post"><div style="margin:0;padding:0;display:inline"><input name="_method" type="hidden" value="put" /></div></form>)
  1671
+    expected = whole_form(admin_comment_path(@post, @comment), "edit_comment_1", "edit_comment", "put")
1649 1672
     assert_dom_equal expected, output_buffer
1650 1673
   end
1651 1674
 
1652 1675
   def test_form_for_with_new_object_and_namespace_in_list
1653 1676
     form_for([:admin, @post, @comment]) {}
1654 1677
 
1655  
-    expected = %(<form action="#{admin_comments_path(@post)}" class="new_comment" id="new_comment" method="post"></form>)
  1678
+    expected = whole_form(admin_comments_path(@post), "new_comment", "new_comment")
1656 1679
     assert_dom_equal expected, output_buffer
1657 1680
   end
1658 1681
 
1659 1682
   def test_form_for_with_existing_object_and_custom_url
1660 1683
     form_for(@post, :url => "/super_posts") do |f| end
1661 1684
 
1662  
-    expected = "<form action=\"/super_posts\" class=\"edit_post\" id=\"edit_post_123\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input name=\"_method\" type=\"hidden\" value=\"put\" /></div></form>"
  1685
+    expected = whole_form("/super_posts", "edit_post_123", "edit_post", "put")
1663 1686
     assert_equal expected, output_buffer
1664 1687
   end
1665 1688
 
56  actionpack/test/template/form_tag_helper_test.rb
@@ -8,6 +8,36 @@ def setup
8 8
     @controller = BasicController.new
9 9
   end
10 10
 
  11
+  def snowman(options = {})
  12
+    method = options[:method]
  13
+
  14
+    txt =  %{<div style="margin:0;padding:0;display:inline">}
  15
+    txt << %{<input name="_snowman_" type="hidden" value="&#9731;" />}
  16
+    txt << %{<input name="_method" type="hidden" value="#{method}" />} if method
  17
+    txt << %{</div>}
  18
+  end
  19
+
  20
+  def form_text(action = "http://www.example.com", options = {})
  21
+    remote, enctype, html_class, id = options.values_at(:remote, :enctype, :html_class, :id)
  22
+
  23
+    txt =  %{<form accept-charset="UTF-8" action="#{action}"}
  24
+    txt << %{ enctype="multipart/form-data"} if enctype
  25
+    txt << %{ data-remote="true"} if remote
  26
+    txt << %{ class="#{html_class}"} if html_class
  27
+    txt << %{ id="#{id}"} if id
  28
+    txt << %{ method="post">}
  29
+  end
  30
+
  31
+  def whole_form(action = "http://www.example.com", options = {})
  32
+    out = form_text(action, options) + snowman(options)
  33
+
  34
+    if block_given?
  35
+      out << yield << "</form>"
  36
+    end
  37
+
  38
+    out
  39
+  end
  40
+
11 41
   def url_for(options)
12 42
     if options.is_a?(Hash)
13 43
       "http://www.example.com"
@@ -31,51 +61,57 @@ def test_check_box_tag_id_sanitized
31 61
 
32 62
   def test_form_tag
33 63
     actual = form_tag
34  
-    expected = %(<form action="http://www.example.com" method="post">)
  64
+    expected = whole_form
35 65
     assert_dom_equal expected, actual
36 66
   end
37 67
 
38 68
   def test_form_tag_multipart
39 69
     actual = form_tag({}, { 'multipart' => true })
40  
-    expected = %(<form action="http://www.example.com" enctype="multipart/form-data" method="post">)
  70
+    expected = whole_form("http://www.example.com", :enctype => true)
41 71
     assert_dom_equal expected, actual
42 72
   end
43 73
 
44 74
   def test_form_tag_with_method_put
45 75
     actual = form_tag({}, { :method => :put })
46  
-    expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="put" /></div>)
  76
+    expected = whole_form("http://www.example.com", :method => :put)
47 77
     assert_dom_equal expected, actual
48 78
   end
49 79
 
50 80
   def test_form_tag_with_method_delete
51 81
     actual = form_tag({}, { :method => :delete })
52  
-    expected = %(<form action="http://www.example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="delete" /></div>)
  82
+
  83
+    expected = whole_form("http://www.example.com", :method => :delete)
53 84
     assert_dom_equal expected, actual
54 85
   end
55 86
 
56 87
   def test_form_tag_with_remote
57 88
     actual = form_tag({}, :remote => true)
58  
-    expected = %(<form action="http://www.example.com" method="post" data-remote="true">)
  89
+
  90
+    expected = whole_form("http://www.example.com", :remote => true)
59 91
     assert_dom_equal expected, actual
60 92
   end
61 93
 
62 94
   def test_form_tag_with_remote_false
63 95
     actual = form_tag({}, :remote => false)
64  
-    expected = %(<form action="http://www.example.com" method="post">)
  96
+
  97
+    expected = whole_form
65 98
     assert_dom_equal expected, actual
66 99
   end
67 100
 
68 101
   def test_form_tag_with_block_in_erb
69  
-    output_buffer = form_tag("http://example.com") { concat "Hello world!" }
  102
+    output_buffer = form_tag("http://www.example.com") { concat "Hello world!" }
70 103
 
71  
-    expected = %(<form action="http://example.com" method="post">Hello world!</form>)
  104
+    expected = whole_form { "Hello world!" }
72 105
     assert_dom_equal expected, output_buffer
73 106
   end
74 107
 
75 108
   def test_form_tag_with_block_and_method_in_erb
76  
-    output_buffer = form_tag("http://example.com", :method => :put) { concat "Hello world!" }
  109
+    output_buffer = form_tag("http://www.example.com", :method => :put) { concat "Hello world!" }
  110
+
  111
+    expected = whole_form("http://www.example.com", :method => "put") do
  112
+      "Hello world!"
  113
+    end
77 114
 
78  
-    expected = %(<form action="http://example.com" method="post"><div style='margin:0;padding:0;display:inline'><input type="hidden" name="_method" value="put" /></div>Hello world!</form>)
79 115
     assert_dom_equal expected, output_buffer
80 116
   end
81 117
 

31 notes on commit 25215d7

Jonas Grimfelt

Hmm...what's the motivation behind supporting IE5? Curious as I haven't seen IE5 showing up in any browser stats in years.

José Valim
Owner

IE5+ (emphasis in the +) ;)

Jeremy Walker
iHiD commented on 25215d7 June 28, 2010

Can I suggest documenting the snowman tag? I just saw this in a HTTP trace and panicked somewhat in case my server had been compromised. I just think sending a new variable with every form request is something that people should know about.

Thanks,
iHiD

Jonas Grimfelt

Aha. :)

Alex MacCaw

Woah - was pretty surprised when I saw snowman in my log today.

aaronchi