formtastic 2.1.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +4 -2
  5. data/CHANGELOG.md +52 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +105 -0
  8. data/MIT-LICENSE +1 -1
  9. data/{README.textile → README.md} +204 -219
  10. data/RELEASE_PROCESS +3 -1
  11. data/Rakefile +27 -29
  12. data/app/assets/stylesheets/formtastic.css +3 -2
  13. data/bin/appraisal +8 -0
  14. data/formtastic.gemspec +11 -14
  15. data/gemfiles/rails_5.2/Gemfile +5 -0
  16. data/gemfiles/rails_6.0/Gemfile +5 -0
  17. data/gemfiles/rails_6.1/Gemfile +5 -0
  18. data/gemfiles/rails_edge/Gemfile +13 -0
  19. data/lib/formtastic/action_class_finder.rb +18 -0
  20. data/lib/formtastic/actions/button_action.rb +55 -60
  21. data/lib/formtastic/actions/input_action.rb +59 -57
  22. data/lib/formtastic/actions/link_action.rb +68 -67
  23. data/lib/formtastic/actions.rb +6 -3
  24. data/lib/formtastic/deprecation.rb +5 -0
  25. data/lib/formtastic/engine.rb +3 -1
  26. data/lib/formtastic/form_builder.rb +35 -16
  27. data/lib/formtastic/helpers/action_helper.rb +34 -28
  28. data/lib/formtastic/helpers/enum.rb +13 -0
  29. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  30. data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -12
  31. data/lib/formtastic/helpers/form_helper.rb +19 -16
  32. data/lib/formtastic/helpers/input_helper.rb +69 -97
  33. data/lib/formtastic/helpers/inputs_helper.rb +35 -25
  34. data/lib/formtastic/helpers/reflection.rb +4 -4
  35. data/lib/formtastic/helpers.rb +1 -2
  36. data/lib/formtastic/html_attributes.rb +12 -1
  37. data/lib/formtastic/i18n.rb +1 -1
  38. data/lib/formtastic/input_class_finder.rb +18 -0
  39. data/lib/formtastic/inputs/base/choices.rb +2 -2
  40. data/lib/formtastic/inputs/base/collections.rb +46 -14
  41. data/lib/formtastic/inputs/base/database.rb +7 -2
  42. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  43. data/lib/formtastic/inputs/base/errors.rb +7 -7
  44. data/lib/formtastic/inputs/base/hints.rb +2 -2
  45. data/lib/formtastic/inputs/base/html.rb +10 -9
  46. data/lib/formtastic/inputs/base/labelling.rb +5 -8
  47. data/lib/formtastic/inputs/base/naming.rb +4 -4
  48. data/lib/formtastic/inputs/base/numeric.rb +1 -1
  49. data/lib/formtastic/inputs/base/options.rb +3 -4
  50. data/lib/formtastic/inputs/base/stringish.rb +10 -2
  51. data/lib/formtastic/inputs/base/timeish.rb +34 -22
  52. data/lib/formtastic/inputs/base/validations.rb +41 -13
  53. data/lib/formtastic/inputs/base/wrapping.rb +29 -26
  54. data/lib/formtastic/inputs/base.rb +22 -15
  55. data/lib/formtastic/inputs/boolean_input.rb +26 -12
  56. data/lib/formtastic/inputs/check_boxes_input.rb +39 -31
  57. data/lib/formtastic/inputs/color_input.rb +41 -0
  58. data/lib/formtastic/inputs/country_input.rb +24 -5
  59. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  60. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  61. data/lib/formtastic/inputs/{date_input.rb → date_select_input.rb} +1 -1
  62. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  63. data/lib/formtastic/inputs/{datetime_input.rb → datetime_select_input.rb} +1 -1
  64. data/lib/formtastic/inputs/file_input.rb +2 -2
  65. data/lib/formtastic/inputs/hidden_input.rb +2 -6
  66. data/lib/formtastic/inputs/radio_input.rb +28 -22
  67. data/lib/formtastic/inputs/select_input.rb +36 -39
  68. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  69. data/lib/formtastic/inputs/{time_input.rb → time_select_input.rb} +6 -2
  70. data/lib/formtastic/inputs/time_zone_input.rb +16 -6
  71. data/lib/formtastic/inputs.rb +32 -21
  72. data/lib/formtastic/localized_string.rb +1 -1
  73. data/lib/formtastic/localizer.rb +24 -24
  74. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  75. data/lib/formtastic/version.rb +1 -1
  76. data/lib/formtastic.rb +20 -10
  77. data/lib/generators/formtastic/form/form_generator.rb +10 -4
  78. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  79. data/lib/generators/formtastic/install/install_generator.rb +5 -19
  80. data/lib/generators/templates/_form.html.slim +2 -2
  81. data/lib/generators/templates/formtastic.rb +46 -25
  82. data/lib/generators/templates/input.rb +19 -0
  83. data/sample/basic_inputs.html +23 -3
  84. data/script/integration-template.rb +74 -0
  85. data/script/integration.sh +19 -0
  86. data/spec/action_class_finder_spec.rb +12 -0
  87. data/spec/actions/button_action_spec.rb +8 -8
  88. data/spec/actions/generic_action_spec.rb +92 -56
  89. data/spec/actions/input_action_spec.rb +7 -7
  90. data/spec/actions/link_action_spec.rb +10 -10
  91. data/spec/builder/custom_builder_spec.rb +36 -20
  92. data/spec/builder/error_proc_spec.rb +4 -4
  93. data/spec/builder/semantic_fields_for_spec.rb +28 -29
  94. data/spec/fast_spec_helper.rb +12 -0
  95. data/spec/generators/formtastic/form/form_generator_spec.rb +45 -32
  96. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  97. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  98. data/spec/helpers/action_helper_spec.rb +75 -103
  99. data/spec/helpers/actions_helper_spec.rb +17 -17
  100. data/spec/helpers/form_helper_spec.rb +84 -33
  101. data/spec/helpers/input_helper_spec.rb +333 -285
  102. data/spec/helpers/inputs_helper_spec.rb +167 -121
  103. data/spec/helpers/reflection_helper_spec.rb +3 -3
  104. data/spec/helpers/semantic_errors_helper_spec.rb +23 -23
  105. data/spec/i18n_spec.rb +26 -26
  106. data/spec/input_class_finder_spec.rb +10 -0
  107. data/spec/inputs/base/collections_spec.rb +76 -0
  108. data/spec/inputs/base/validations_spec.rb +480 -0
  109. data/spec/inputs/boolean_input_spec.rb +100 -65
  110. data/spec/inputs/check_boxes_input_spec.rb +200 -101
  111. data/spec/inputs/color_input_spec.rb +85 -0
  112. data/spec/inputs/country_input_spec.rb +20 -20
  113. data/spec/inputs/custom_input_spec.rb +3 -4
  114. data/spec/inputs/datalist_input_spec.rb +61 -0
  115. data/spec/inputs/date_picker_input_spec.rb +449 -0
  116. data/spec/inputs/date_select_input_spec.rb +249 -0
  117. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  118. data/spec/inputs/datetime_select_input_spec.rb +209 -0
  119. data/spec/inputs/email_input_spec.rb +5 -5
  120. data/spec/inputs/file_input_spec.rb +6 -6
  121. data/spec/inputs/hidden_input_spec.rb +22 -35
  122. data/spec/inputs/include_blank_spec.rb +11 -11
  123. data/spec/inputs/label_spec.rb +62 -25
  124. data/spec/inputs/number_input_spec.rb +112 -112
  125. data/spec/inputs/password_input_spec.rb +5 -5
  126. data/spec/inputs/phone_input_spec.rb +5 -5
  127. data/spec/inputs/placeholder_spec.rb +6 -6
  128. data/spec/inputs/radio_input_spec.rb +99 -55
  129. data/spec/inputs/range_input_spec.rb +66 -66
  130. data/spec/inputs/readonly_spec.rb +50 -0
  131. data/spec/inputs/search_input_spec.rb +5 -5
  132. data/spec/inputs/select_input_spec.rb +170 -170
  133. data/spec/inputs/string_input_spec.rb +68 -16
  134. data/spec/inputs/text_input_spec.rb +16 -16
  135. data/spec/inputs/time_picker_input_spec.rb +455 -0
  136. data/spec/inputs/time_select_input_spec.rb +261 -0
  137. data/spec/inputs/time_zone_input_spec.rb +54 -28
  138. data/spec/inputs/url_input_spec.rb +5 -5
  139. data/spec/inputs/with_options_spec.rb +7 -7
  140. data/spec/localizer_spec.rb +39 -17
  141. data/spec/namespaced_class_finder_spec.rb +79 -0
  142. data/spec/schema.rb +21 -0
  143. data/spec/spec_helper.rb +254 -221
  144. data/spec/support/custom_macros.rb +128 -95
  145. data/spec/support/shared_examples.rb +12 -0
  146. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  147. data/spec/support/test_environment.rb +26 -10
  148. metadata +177 -238
  149. data/.travis.yml +0 -8
  150. data/Appraisals +0 -11
  151. data/CHANGELOG +0 -371
  152. data/gemfiles/rails-3.0.gemfile +0 -7
  153. data/gemfiles/rails-3.1.gemfile +0 -7
  154. data/gemfiles/rails-3.2.gemfile +0 -7
  155. data/lib/formtastic/helpers/buttons_helper.rb +0 -310
  156. data/lib/formtastic/inputs/base/grouped_collections.rb +0 -77
  157. data/lib/formtastic/util.rb +0 -25
  158. data/lib/tasks/verify_rcov.rb +0 -44
  159. data/spec/helpers/buttons_helper_spec.rb +0 -166
  160. data/spec/helpers/commit_button_helper_spec.rb +0 -530
  161. data/spec/inputs/date_input_spec.rb +0 -227
  162. data/spec/inputs/datetime_input_spec.rb +0 -185
  163. data/spec/inputs/time_input_spec.rb +0 -267
  164. data/spec/support/deferred_garbage_collection.rb +0 -21
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require 'spec_helper'
3
3
 
4
- describe 'FormHelper' do
4
+ RSpec.describe 'FormHelper' do
5
5
 
6
6
  include FormtasticSpecHelper
7
7
 
@@ -14,45 +14,45 @@ describe 'FormHelper' do
14
14
 
15
15
  it 'yields an instance of Formtastic::FormBuilder' do
16
16
  semantic_form_for(@new_post, :url => '/hello') do |builder|
17
- builder.class.should == Formtastic::FormBuilder
17
+ expect(builder.class).to eq(Formtastic::FormBuilder)
18
18
  end
19
19
  end
20
20
 
21
21
  it 'adds a class of "formtastic" to the generated form' do
22
22
  concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
23
23
  end)
24
- output_buffer.should have_tag("form.formtastic")
24
+ expect(output_buffer).to have_tag("form.formtastic")
25
25
  end
26
-
27
- it 'adds a "novalidate" attribute to the generated form when configured to do so' do
26
+
27
+ it 'does not add "novalidate" attribute to the generated form when configured to do so' do
28
28
  with_config :perform_browser_validations, true do
29
29
  concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
30
30
  end)
31
- output_buffer.should_not have_tag("form[@novalidate]")
31
+ expect(output_buffer).not_to have_tag("form[@novalidate]")
32
32
  end
33
33
  end
34
-
35
- it 'omits a "novalidate" attribute to the generated form when configured to do so' do
34
+
35
+ it 'adds "novalidate" attribute to the generated form when configured to do so' do
36
36
  with_config :perform_browser_validations, false do
37
37
  concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
38
38
  end)
39
- output_buffer.should have_tag("form[@novalidate]")
39
+ expect(output_buffer).to have_tag("form[@novalidate]")
40
40
  end
41
41
  end
42
42
 
43
- it 'allows form HTML to override "novalidate" attribute when configure to not show' do
43
+ it 'allows form HTML to override "novalidate" attribute when configured to validate' do
44
44
  with_config :perform_browser_validations, false do
45
45
  concat(semantic_form_for(@new_post, :url => '/hello', :html => { :novalidate => true }) do |builder|
46
46
  end)
47
- output_buffer.should have_tag("form[@novalidate]")
47
+ expect(output_buffer).to have_tag("form[@novalidate]")
48
48
  end
49
49
  end
50
50
 
51
- it 'allows form HTML to override "novalidate" attribute when configure to show' do
51
+ it 'allows form HTML to override "novalidate" attribute when configured to not validate' do
52
52
  with_config :perform_browser_validations, true do
53
53
  concat(semantic_form_for(@new_post, :url => '/hello', :html => { :novalidate => false }) do |builder|
54
54
  end)
55
- output_buffer.should_not have_tag("form[@novalidate]")
55
+ expect(output_buffer).not_to have_tag("form[@novalidate]")
56
56
  end
57
57
  end
58
58
 
@@ -60,78 +60,119 @@ describe 'FormHelper' do
60
60
  Formtastic::Helpers::FormHelper.default_form_class = 'xyz'
61
61
  concat(semantic_form_for(::Post.new, :as => :post, :url => '/hello') do |builder|
62
62
  end)
63
- output_buffer.should have_tag("form.xyz")
63
+ expect(output_buffer).to have_tag("form.xyz")
64
+ end
65
+
66
+ it 'omits the leading spaces from the classes in the generated form when the default class is nil' do
67
+ Formtastic::Helpers::FormHelper.default_form_class = nil
68
+ concat(semantic_form_for(::Post.new, :as => :post, :url => '/hello') do |builder|
69
+ end)
70
+ expect(output_buffer).to have_tag("form[class='post']")
64
71
  end
65
72
 
66
73
  it 'adds class matching the object name to the generated form when a symbol is provided' do
67
74
  concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
68
75
  end)
69
- output_buffer.should have_tag("form.post")
76
+ expect(output_buffer).to have_tag("form.post")
70
77
 
71
78
  concat(semantic_form_for(:project, :url => '/hello') do |builder|
72
79
  end)
73
- output_buffer.should have_tag("form.project")
80
+ expect(output_buffer).to have_tag("form.project")
74
81
  end
75
82
 
76
83
  it 'adds class matching the :as option when provided' do
77
84
  concat(semantic_form_for(@new_post, :as => :message, :url => '/hello') do |builder|
78
85
  end)
79
- output_buffer.should have_tag("form.message")
86
+ expect(output_buffer).to have_tag("form.message")
80
87
 
81
88
  concat(semantic_form_for([:admins, @new_post], :as => :message, :url => '/hello') do |builder|
82
89
  end)
83
- output_buffer.should have_tag("form.message")
90
+ expect(output_buffer).to have_tag("form.message")
84
91
  end
85
92
 
86
93
  it 'adds class matching the object\'s class to the generated form when an object is provided' do
87
94
  concat(semantic_form_for(@new_post) do |builder|
88
95
  end)
89
- output_buffer.should have_tag("form.post")
96
+ expect(output_buffer).to have_tag("form.post")
90
97
  end
91
98
 
92
99
  it 'adds a namespaced class to the generated form' do
93
100
  concat(semantic_form_for(::Namespaced::Post.new, :url => '/hello') do |builder|
94
101
  end)
95
- output_buffer.should have_tag("form.namespaced_post")
102
+ expect(output_buffer).to have_tag("form.namespaced_post")
103
+ end
104
+
105
+ it 'adds a customized class to the generated form' do
106
+ Formtastic::Helpers::FormHelper.default_form_model_class_proc = lambda { |model_class_name| "#{model_class_name}_form" }
107
+ concat(semantic_form_for(@new_post, :url => '/hello') do |builder|
108
+ end)
109
+ expect(output_buffer).to have_tag("form.post_form")
110
+
111
+ concat(semantic_form_for(:project, :url => '/hello') do |builder|
112
+ end)
113
+ expect(output_buffer).to have_tag("form.project_form")
96
114
  end
97
115
 
98
116
  describe 'allows :html options' do
99
- before(:each) do
117
+ before(:example) do
100
118
  concat(semantic_form_for(@new_post, :url => '/hello', :html => { :id => "something-special", :class => "something-extra", :multipart => true }) do |builder|
101
119
  end)
102
120
  end
103
121
 
104
122
  it 'to add a id of "something-special" to generated form' do
105
- output_buffer.should have_tag("form#something-special")
123
+ expect(output_buffer).to have_tag("form#something-special")
106
124
  end
107
125
 
108
126
  it 'to add a class of "something-extra" to generated form' do
109
- output_buffer.should have_tag("form.something-extra")
127
+ expect(output_buffer).to have_tag("form.something-extra")
110
128
  end
111
129
 
112
130
  it 'to add enctype="multipart/form-data"' do
113
- output_buffer.should have_tag('form[@enctype="multipart/form-data"]')
131
+ expect(output_buffer).to have_tag('form[@enctype="multipart/form-data"]')
114
132
  end
115
133
  end
116
134
 
117
135
  it 'can be called with a resource-oriented style' do
118
136
  semantic_form_for(@new_post) do |builder|
119
- builder.object.class.should == ::Post
120
- builder.object_name.should == "post"
137
+ expect(builder.object.class).to eq(::Post)
138
+ expect(builder.object_name).to eq("post")
121
139
  end
122
140
  end
123
141
 
124
142
  it 'can be called with a generic style and instance variable' do
125
143
  semantic_form_for(@new_post, :as => :post, :url => new_post_path) do |builder|
126
- builder.object.class.should == ::Post
127
- builder.object_name.to_s.should == "post" # TODO: is this forced .to_s a bad assumption somewhere?
144
+ expect(builder.object.class).to eq(::Post)
145
+ expect(builder.object_name.to_s).to eq("post") # TODO: is this forced .to_s a bad assumption somewhere?
128
146
  end
129
147
  end
130
148
 
131
149
  it 'can be called with a generic style and inline object' do
132
150
  semantic_form_for(@new_post, :url => new_post_path) do |builder|
133
- builder.object.class.should == ::Post
134
- builder.object_name.to_s.should == "post" # TODO: is this forced .to_s a bad assumption somewhere?
151
+ expect(builder.object.class).to eq(::Post)
152
+ expect(builder.object_name.to_s).to eq("post") # TODO: is this forced .to_s a bad assumption somewhere?
153
+ end
154
+ end
155
+
156
+ describe 'ActionView::Base.field_error_proc' do
157
+ it 'is set to no-op wrapper by default' do
158
+ semantic_form_for(@new_post, :url => '/hello') do |builder|
159
+ expect(::ActionView::Base.field_error_proc.call("html", nil)).to eq("html")
160
+ end
161
+ end
162
+
163
+ it 'is set to the configured custom field_error_proc' do
164
+ field_error_proc = double()
165
+ Formtastic::Helpers::FormHelper.formtastic_field_error_proc = field_error_proc
166
+ semantic_form_for(@new_post, :url => '/hello') do |builder|
167
+ expect(::ActionView::Base.field_error_proc).to eq(field_error_proc)
168
+ end
169
+ end
170
+
171
+ it 'is restored to its original value after the form is rendered' do
172
+ expect do
173
+ Formtastic::Helpers::FormHelper.formtastic_field_error_proc = proc {""}
174
+ semantic_form_for(@new_post, :url => '/hello') { |builder| }
175
+ end.not_to change(::ActionView::Base, :field_error_proc)
135
176
  end
136
177
  end
137
178
 
@@ -140,7 +181,7 @@ describe 'FormHelper' do
140
181
  class MyAwesomeCustomBuilder < Formtastic::FormBuilder
141
182
  end
142
183
  semantic_form_for(@new_post, :url => '/hello', :builder => MyAwesomeCustomBuilder) do |builder|
143
- builder.class.should == MyAwesomeCustomBuilder
184
+ expect(builder.class).to eq(MyAwesomeCustomBuilder)
144
185
  end
145
186
  end
146
187
  end
@@ -148,7 +189,17 @@ describe 'FormHelper' do
148
189
  describe 'with :namespace option' do
149
190
  it "should set the custom_namespace" do
150
191
  semantic_form_for(@new_post, :namespace => 'context2') do |builder|
151
- builder.custom_namespace == 'context2'
192
+ expect(builder.dom_id_namespace).to eq('context2')
193
+ end
194
+ end
195
+ end
196
+
197
+ describe 'without :namespace option' do
198
+ it 'defaults to class settings' do
199
+ expect(Formtastic::FormBuilder).to receive(:custom_namespace).and_return('context2')
200
+
201
+ semantic_form_for(@new_post) do |builder|
202
+ expect(builder.dom_id_namespace).to eq('context2')
152
203
  end
153
204
  end
154
205
  end
@@ -158,7 +209,7 @@ describe 'FormHelper' do
158
209
  describe '#semantic_fields_for' do
159
210
  it 'yields an instance of Formtastic::FormBuilder' do
160
211
  semantic_fields_for(@new_post) do |builder|
161
- builder.class.should.kind_of?(Formtastic::FormBuilder)
212
+ expect(builder.class).to be(Formtastic::FormBuilder)
162
213
  end
163
214
  end
164
215
  end