simple_form 3.0.1 → 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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +149 -25
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +441 -107
  5. data/lib/generators/simple_form/install_generator.rb +4 -3
  6. data/lib/generators/simple_form/templates/README +4 -5
  7. data/lib/generators/simple_form/templates/_form.html.erb +2 -0
  8. data/lib/generators/simple_form/templates/_form.html.haml +2 -0
  9. data/lib/generators/simple_form/templates/_form.html.slim +1 -0
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +48 -11
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +417 -23
  12. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +101 -5
  13. data/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +7 -2
  14. data/lib/simple_form/action_view_extensions/builder.rb +2 -0
  15. data/lib/simple_form/action_view_extensions/form_helper.rb +10 -3
  16. data/lib/simple_form/components/errors.rb +38 -3
  17. data/lib/simple_form/components/hints.rb +3 -2
  18. data/lib/simple_form/components/html5.rb +16 -5
  19. data/lib/simple_form/components/label_input.rb +21 -2
  20. data/lib/simple_form/components/labels.rb +22 -11
  21. data/lib/simple_form/components/maxlength.rb +9 -5
  22. data/lib/simple_form/components/min_max.rb +2 -1
  23. data/lib/simple_form/components/minlength.rb +38 -0
  24. data/lib/simple_form/components/pattern.rb +2 -1
  25. data/lib/simple_form/components/placeholders.rb +4 -3
  26. data/lib/simple_form/components/readonly.rb +2 -1
  27. data/lib/simple_form/components.rb +2 -0
  28. data/lib/simple_form/error_notification.rb +1 -0
  29. data/lib/simple_form/form_builder.rb +193 -80
  30. data/lib/simple_form/helpers/autofocus.rb +1 -0
  31. data/lib/simple_form/helpers/disabled.rb +1 -0
  32. data/lib/simple_form/helpers/readonly.rb +1 -0
  33. data/lib/simple_form/helpers/required.rb +1 -0
  34. data/lib/simple_form/helpers/validators.rb +2 -1
  35. data/lib/simple_form/helpers.rb +6 -5
  36. data/lib/simple_form/i18n_cache.rb +1 -0
  37. data/lib/simple_form/inputs/base.rb +57 -14
  38. data/lib/simple_form/inputs/block_input.rb +2 -1
  39. data/lib/simple_form/inputs/boolean_input.rb +39 -16
  40. data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
  41. data/lib/simple_form/inputs/collection_input.rb +37 -14
  42. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +9 -13
  43. data/lib/simple_form/inputs/collection_select_input.rb +5 -2
  44. data/lib/simple_form/inputs/date_time_input.rb +24 -9
  45. data/lib/simple_form/inputs/file_input.rb +5 -2
  46. data/lib/simple_form/inputs/grouped_collection_select_input.rb +16 -3
  47. data/lib/simple_form/inputs/hidden_input.rb +5 -2
  48. data/lib/simple_form/inputs/numeric_input.rb +6 -4
  49. data/lib/simple_form/inputs/password_input.rb +6 -3
  50. data/lib/simple_form/inputs/priority_input.rb +5 -2
  51. data/lib/simple_form/inputs/range_input.rb +2 -1
  52. data/lib/simple_form/inputs/string_input.rb +6 -3
  53. data/lib/simple_form/inputs/text_input.rb +6 -3
  54. data/lib/simple_form/inputs.rb +1 -0
  55. data/lib/simple_form/map_type.rb +1 -0
  56. data/lib/simple_form/railtie.rb +8 -0
  57. data/lib/simple_form/tags.rb +7 -0
  58. data/lib/simple_form/version.rb +2 -1
  59. data/lib/simple_form/wrappers/builder.rb +7 -6
  60. data/lib/simple_form/wrappers/leaf.rb +29 -0
  61. data/lib/simple_form/wrappers/many.rb +7 -6
  62. data/lib/simple_form/wrappers/root.rb +3 -1
  63. data/lib/simple_form/wrappers/single.rb +7 -4
  64. data/lib/simple_form/wrappers.rb +2 -0
  65. data/lib/simple_form.rb +117 -18
  66. data/test/action_view_extensions/builder_test.rb +42 -41
  67. data/test/action_view_extensions/form_helper_test.rb +36 -16
  68. data/test/components/custom_components_test.rb +62 -0
  69. data/test/components/label_test.rb +70 -41
  70. data/test/form_builder/association_test.rb +79 -37
  71. data/test/form_builder/button_test.rb +11 -10
  72. data/test/form_builder/error_notification_test.rb +2 -1
  73. data/test/form_builder/error_test.rb +173 -24
  74. data/test/form_builder/general_test.rb +171 -73
  75. data/test/form_builder/hint_test.rb +24 -18
  76. data/test/form_builder/input_field_test.rb +132 -56
  77. data/test/form_builder/label_test.rb +68 -13
  78. data/test/form_builder/wrapper_test.rb +190 -22
  79. data/test/generators/simple_form_generator_test.rb +8 -7
  80. data/test/inputs/boolean_input_test.rb +89 -6
  81. data/test/inputs/collection_check_boxes_input_test.rb +109 -25
  82. data/test/inputs/collection_radio_buttons_input_test.rb +168 -54
  83. data/test/inputs/collection_select_input_test.rb +183 -77
  84. data/test/inputs/datetime_input_test.rb +131 -50
  85. data/test/inputs/disabled_test.rb +16 -15
  86. data/test/inputs/discovery_test.rb +58 -6
  87. data/test/inputs/file_input_test.rb +3 -2
  88. data/test/inputs/general_test.rb +23 -22
  89. data/test/inputs/grouped_collection_select_input_test.rb +54 -17
  90. data/test/inputs/hidden_input_test.rb +5 -4
  91. data/test/inputs/numeric_input_test.rb +48 -44
  92. data/test/inputs/priority_input_test.rb +23 -14
  93. data/test/inputs/readonly_test.rb +20 -19
  94. data/test/inputs/required_test.rb +58 -13
  95. data/test/inputs/string_input_test.rb +62 -33
  96. data/test/inputs/text_input_test.rb +20 -7
  97. data/test/simple_form_test.rb +9 -0
  98. data/test/support/discovery_inputs.rb +33 -2
  99. data/test/support/misc_helpers.rb +113 -5
  100. data/test/support/mock_controller.rb +7 -1
  101. data/test/support/models.rb +137 -37
  102. data/test/test_helper.rb +15 -1
  103. metadata +25 -33
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  # A wrapper is an object that holds several components and render them.
4
- # A component may either be a symbol or any object that responds to `render`.
5
+ # A component may be any object that responds to `render`.
5
6
  # This API allows inputs/components to be easily wrapped, removing the
6
7
  # need to modify the code only to wrap input in an extra tag.
7
8
  #
@@ -10,9 +11,8 @@ module SimpleForm
10
11
  # on demand on input generation.
11
12
  class Many
12
13
  attr_reader :namespace, :defaults, :components
13
- alias :to_sym :namespace
14
14
 
15
- def initialize(namespace, components, defaults={})
15
+ def initialize(namespace, components, defaults = {})
16
16
  @namespace = namespace
17
17
  @components = components
18
18
  @defaults = defaults
@@ -25,8 +25,8 @@ module SimpleForm
25
25
  options = input.options
26
26
 
27
27
  components.each do |component|
28
- next if options[component] == false
29
- rendered = component.respond_to?(:render) ? component.render(input) : input.send(component)
28
+ next if options[component.namespace] == false
29
+ rendered = component.render(input)
30
30
  content.safe_concat rendered.to_s if rendered
31
31
  end
32
32
 
@@ -51,6 +51,7 @@ module SimpleForm
51
51
 
52
52
  def wrap(input, options, content)
53
53
  return content if options[namespace] == false
54
+ return if defaults[:unless_blank] && content.empty?
54
55
 
55
56
  tag = (namespace && options[:"#{namespace}_tag"]) || @defaults[:tag]
56
57
  return content unless tag
@@ -62,7 +63,7 @@ module SimpleForm
62
63
  end
63
64
 
64
65
  def html_options(options)
65
- options[:"#{namespace}_html"] || {}
66
+ (@defaults[:html] || {}).merge(options[:"#{namespace}_html"] || {})
66
67
  end
67
68
 
68
69
  def html_classes(input, options)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  # `Root` is the root wrapper for all components. It is special cased to
@@ -17,7 +18,7 @@ module SimpleForm
17
18
 
18
19
  # Provide a fallback if name cannot be found.
19
20
  def find(name)
20
- super || SimpleForm::Wrappers::Many.new(name, [name])
21
+ super || SimpleForm::Wrappers::Many.new(name, [Leaf.new(name)])
21
22
  end
22
23
 
23
24
  private
@@ -29,6 +30,7 @@ module SimpleForm
29
30
  end
30
31
  css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
31
32
  css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
33
+ css << (options[:wrapper_valid_class] || @defaults[:valid_class]) if input.valid?
32
34
  css.compact
33
35
  end
34
36
  end
@@ -1,15 +1,18 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  # `Single` is an optimization for a wrapper that has only one component.
4
5
  class Single < Many
5
- def initialize(name, options={})
6
- super(name, [name], options)
6
+ def initialize(name, wrapper_options = {}, options = {})
7
+ @component = Leaf.new(name, options)
8
+
9
+ super(name, [@component], wrapper_options)
7
10
  end
8
11
 
9
12
  def render(input)
10
13
  options = input.options
11
14
  if options[namespace] != false
12
- content = input.send(namespace)
15
+ content = @component.render(input)
13
16
  wrap(input, options, content) if content
14
17
  end
15
18
  end
@@ -17,7 +20,7 @@ module SimpleForm
17
20
  private
18
21
 
19
22
  def html_options(options)
20
- [:label, :input].include?(namespace) ? {} : super
23
+ %i[label input].include?(namespace) ? {} : super
21
24
  end
22
25
  end
23
26
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  autoload :Builder, 'simple_form/wrappers/builder'
4
5
  autoload :Many, 'simple_form/wrappers/many'
5
6
  autoload :Root, 'simple_form/wrappers/root'
6
7
  autoload :Single, 'simple_form/wrappers/single'
8
+ autoload :Leaf, 'simple_form/wrappers/leaf'
7
9
  end
8
10
  end
data/lib/simple_form.rb CHANGED
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  require 'action_view'
3
+ require 'action_pack'
2
4
  require 'simple_form/action_view_extensions/form_helper'
3
5
  require 'simple_form/action_view_extensions/builder'
4
6
  require 'active_support/core_ext/hash/slice'
@@ -24,6 +26,24 @@ module SimpleForm
24
26
  SimpleForm::Components.eager_load!
25
27
  end
26
28
 
29
+ CUSTOM_INPUT_DEPRECATION_WARN = <<-WARN
30
+ %{name} method now accepts a `wrapper_options` argument. The method definition without the argument is deprecated and will be removed in the next Simple Form version. Change your code from:
31
+
32
+ def %{name}
33
+
34
+ to
35
+
36
+ def %{name}(wrapper_options)
37
+
38
+ See https://github.com/plataformatec/simple_form/pull/997 for more information.
39
+ WARN
40
+
41
+ @@configured = false
42
+
43
+ def self.configured? #:nodoc:
44
+ @@configured
45
+ end
46
+
27
47
  ## CONFIGURATION OPTIONS
28
48
 
29
49
  # Method used to tidy up errors.
@@ -40,11 +60,11 @@ module SimpleForm
40
60
 
41
61
  # Series of attemps to detect a default label method for collection.
42
62
  mattr_accessor :collection_label_methods
43
- @@collection_label_methods = [:to_label, :name, :title, :to_s]
63
+ @@collection_label_methods = %i[to_label name title to_s]
44
64
 
45
65
  # Series of attemps to detect a default value method for collection.
46
66
  mattr_accessor :collection_value_methods
47
- @@collection_value_methods = [:id, :to_s]
67
+ @@collection_value_methods = %i[id to_s]
48
68
 
49
69
  # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
50
70
  mattr_accessor :collection_wrapper_tag
@@ -66,7 +86,7 @@ module SimpleForm
66
86
 
67
87
  # How the label text should be generated altogether with the required text.
68
88
  mattr_accessor :label_text
69
- @@label_text = lambda { |label, required| "#{required} #{label}" }
89
+ @@label_text = ->(label, required, explicit_label) { "#{required} #{label}" }
70
90
 
71
91
  # You can define the class to be used on all labels. Defaults to none.
72
92
  mattr_accessor :label_class
@@ -78,13 +98,19 @@ module SimpleForm
78
98
  mattr_accessor :boolean_style
79
99
  @@boolean_style = :inline
80
100
 
81
- # You can define the class to be used on all forms. Default is simple_form.
82
- mattr_accessor :form_class
101
+ # DEPRECATED: You can define the class to be used on all forms. Default is
102
+ # simple_form.
103
+ mattr_reader :form_class
83
104
  @@form_class = :simple_form
84
105
 
106
+ # You can define the default class to be used on all forms. Can be overriden
107
+ # with `html: { :class }`. Defaults to none.
108
+ mattr_accessor :default_form_class
109
+ @@default_form_class = nil
110
+
85
111
  # You can define which elements should obtain additional classes.
86
112
  mattr_accessor :generate_additional_classes_for
87
- @@generate_additional_classes_for = [:wrapper, :label, :input]
113
+ @@generate_additional_classes_for = %i[wrapper label input]
88
114
 
89
115
  # Whether attributes are required by default or not.
90
116
  mattr_accessor :required_by_default
@@ -96,7 +122,7 @@ module SimpleForm
96
122
 
97
123
  # Collection of methods to detect if a file type was given.
98
124
  mattr_accessor :file_methods
99
- @@file_methods = [:mounted_as, :file?, :public_filename]
125
+ @@file_methods = %i[mounted_as file? public_filename attached?]
100
126
 
101
127
  # Custom mappings for input types. This should be a hash containing a regexp
102
128
  # to match as key, and the input type that will be used when the field name
@@ -107,9 +133,19 @@ module SimpleForm
107
133
  # Custom wrappers for input types. This should be a hash containing an input
108
134
  # type as key and the wrapper that will be used for all inputs with specified type.
109
135
  # e.g { string: :string_wrapper, boolean: :boolean_wrapper }
136
+ # You can also set a wrapper mapping per form basis.
137
+ # e.g simple_form_for(@foo, wrapper_mappings: { check_boxes: :bootstrap_checkbox })
110
138
  mattr_accessor :wrapper_mappings
111
139
  @@wrapper_mappings = nil
112
140
 
141
+ # Namespaces where SimpleForm should look for custom input classes that override
142
+ # default inputs. Namespaces are given as string to allow lazy loading inputs.
143
+ # e.g. config.custom_inputs_namespaces << "CustomInputs"
144
+ # will try to find CustomInputs::NumericInput when an :integer
145
+ # field is called.
146
+ mattr_accessor :custom_inputs_namespaces
147
+ @@custom_inputs_namespaces = []
148
+
113
149
  # Default priority for time_zone inputs.
114
150
  mattr_accessor :time_zone_priority
115
151
  @@time_zone_priority = nil
@@ -118,10 +154,6 @@ module SimpleForm
118
154
  mattr_accessor :country_priority
119
155
  @@country_priority = nil
120
156
 
121
- # DEPRECATED: Maximum size allowed for inputs.
122
- mattr_accessor :default_input_size
123
- @@default_input_size = nil
124
-
125
157
  # When off, do not use translations in labels. Disabling translation in
126
158
  # hints and placeholders can be done manually in the wrapper API.
127
159
  mattr_accessor :translate_labels
@@ -133,7 +165,7 @@ module SimpleForm
133
165
 
134
166
  # Cache SimpleForm inputs discovery.
135
167
  mattr_accessor :cache_discovery
136
- @@cache_discovery = defined?(Rails) && !Rails.env.development?
168
+ @@cache_discovery = defined?(Rails.env) && !Rails.env.development?
137
169
 
138
170
  # Adds a class to each generated button, mostly for compatiblity.
139
171
  mattr_accessor :button_class
@@ -151,15 +183,32 @@ module SimpleForm
151
183
  mattr_accessor :input_class
152
184
  @@input_class = nil
153
185
 
186
+ # Defines if an input wrapper class should be included or not
187
+ mattr_accessor :include_default_input_wrapper_class
188
+ @@include_default_input_wrapper_class = true
189
+
190
+ # Define the default class of the input wrapper of the boolean input.
191
+ mattr_accessor :boolean_label_class
192
+ @@boolean_label_class = 'checkbox'
193
+
154
194
  ## WRAPPER CONFIGURATION
155
195
  # The default wrapper to be used by the FormBuilder.
156
196
  mattr_accessor :default_wrapper
157
197
  @@default_wrapper = :default
158
- @@wrappers = {}
198
+ @@wrappers = {} #:nodoc:
199
+
200
+ mattr_accessor :i18n_scope
201
+ @@i18n_scope = 'simple_form'
202
+
203
+ mattr_accessor :input_field_error_class
204
+ @@input_field_error_class = nil
205
+
206
+ mattr_accessor :input_field_valid_class
207
+ @@input_field_valid_class = nil
159
208
 
160
209
  # Retrieves a given wrapper
161
210
  def self.wrapper(name)
162
- @@wrappers[name.to_sym] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
211
+ @@wrappers[name.to_s] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
163
212
  end
164
213
 
165
214
  # Raised when fails to find a given wrapper name
@@ -172,25 +221,26 @@ module SimpleForm
172
221
  if block_given?
173
222
  options = args.extract_options!
174
223
  name = args.first || :default
175
- @@wrappers[name.to_sym] = build(options, &block)
224
+ @@wrappers[name.to_s] = build(options, &block)
176
225
  else
177
226
  @@wrappers
178
227
  end
179
228
  end
180
229
 
181
230
  # Builds a new wrapper using SimpleForm::Wrappers::Builder.
182
- def self.build(options={})
231
+ def self.build(options = {})
183
232
  options[:tag] = :div if options[:tag].nil?
184
233
  builder = SimpleForm::Wrappers::Builder.new(options)
185
234
  yield builder
186
235
  SimpleForm::Wrappers::Root.new(builder.to_a, options)
187
236
  end
188
237
 
189
- wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
238
+ wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
190
239
  b.use :html5
191
240
 
192
241
  b.use :min_max
193
242
  b.use :maxlength
243
+ b.use :minlength
194
244
  b.use :placeholder
195
245
  b.optional :pattern
196
246
  b.optional :readonly
@@ -210,11 +260,60 @@ module SimpleForm
210
260
  ActiveSupport::Deprecation.warn "[SIMPLE_FORM] SimpleForm.default_input_size= is deprecated and has no effect", caller
211
261
  end
212
262
 
213
- # Default way to setup SimpleForm. Run rails generate simple_form:install
263
+ def self.form_class=(value)
264
+ ActiveSupport::Deprecation.warn "[SIMPLE_FORM] SimpleForm.form_class= is deprecated and will be removed in 4.x. Use SimpleForm.default_form_class= instead", caller
265
+ @@form_class = value
266
+ end
267
+
268
+ # Default way to setup Simple Form. Run rails generate simple_form:install
214
269
  # to create a fresh initializer with all configuration values.
215
270
  def self.setup
271
+ @@configured = true
216
272
  yield self
217
273
  end
274
+
275
+ # Includes a component to be used by Simple Form. Methods defined in a
276
+ # component will be exposed to be used in the wrapper as Simple::Components
277
+ #
278
+ # Examples
279
+ #
280
+ # # The application needs to tell where the components will be.
281
+ # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
282
+ #
283
+ # # Create a custom component in the path specified above.
284
+ # # lib/components/input_group_component.rb
285
+ # module InputGroupComponent
286
+ # def prepend
287
+ # ...
288
+ # end
289
+ #
290
+ # def append
291
+ # ...
292
+ # end
293
+ # end
294
+ #
295
+ # SimpleForm.setup do |config|
296
+ # # Create a wrapper using the custom component.
297
+ # config.wrappers :input_group, tag: :div, error_class: :error do |b|
298
+ # b.use :label
299
+ # b.optional :prepend
300
+ # b.use :input
301
+ # b.use :append
302
+ # end
303
+ # end
304
+ #
305
+ # # Using the custom component in the form.
306
+ # <%= simple_form_for @blog, wrapper: input_group do |f| %>
307
+ # <%= f.input :title, prepend: true %>
308
+ # <% end %>
309
+ #
310
+ def self.include_component(component)
311
+ if Module === component
312
+ SimpleForm::Inputs::Base.include(component)
313
+ else
314
+ raise TypeError, "SimpleForm.include_component expects a module but got: #{component.class}"
315
+ end
316
+ end
218
317
  end
219
318
 
220
319
  require 'simple_form/railtie' if defined?(Rails)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class BuilderTest < ActionView::TestCase
@@ -8,13 +9,13 @@ class BuilderTest < ActionView::TestCase
8
9
  end
9
10
  end
10
11
 
11
- def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
12
+ def with_collection_radio_buttons(object, attribute, collection, value_method, text_method, options = {}, html_options = {}, &block)
12
13
  with_concat_form_for(object) do |f|
13
14
  f.collection_radio_buttons attribute, collection, value_method, text_method, options, html_options, &block
14
15
  end
15
16
  end
16
17
 
17
- def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options={}, html_options={}, &block)
18
+ def with_collection_check_boxes(object, attribute, collection, value_method, text_method, options = {}, html_options = {}, &block)
18
19
  with_concat_form_for(object) do |f|
19
20
  f.collection_check_boxes attribute, collection, value_method, text_method, options, html_options, &block
20
21
  end
@@ -36,13 +37,13 @@ class BuilderTest < ActionView::TestCase
36
37
  end
37
38
 
38
39
  test "collection radio handles camelized collection values for labels correctly" do
39
- with_collection_radio_buttons @user, :active, ['Yes', 'No'], :to_s, :to_s
40
+ with_collection_radio_buttons @user, :active, %w[Yes No], :to_s, :to_s
40
41
 
41
42
  assert_select 'form label.collection_radio_buttons[for=user_active_yes]', 'Yes'
42
43
  assert_select 'form label.collection_radio_buttons[for=user_active_no]', 'No'
43
44
  end
44
45
 
45
- test "collection radio should sanitize collection values for labels correctly" do
46
+ test "collection radio sanitizes collection values for labels correctly" do
46
47
  with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
47
48
  assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
48
49
  assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
@@ -243,7 +244,7 @@ class BuilderTest < ActionView::TestCase
243
244
 
244
245
  test "collection radio with block helpers does not leak the template" do
245
246
  with_concat_form_for(@user) do |f|
246
- collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
247
+ collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
247
248
  b.label(class: b.object) { b.radio_button + b.text }
248
249
  end
249
250
  concat collection_input
@@ -263,15 +264,15 @@ class BuilderTest < ActionView::TestCase
263
264
  collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
264
265
  with_collection_check_boxes @user, :tag_ids, collection, :id, :name
265
266
 
266
- assert_select 'form input#user_tag_ids_1[type=checkbox][value=1]'
267
- assert_select 'form input#user_tag_ids_2[type=checkbox][value=2]'
267
+ assert_select 'form input#user_tag_ids_1[type=checkbox][value="1"]'
268
+ assert_select 'form input#user_tag_ids_2[type=checkbox][value="2"]'
268
269
  end
269
270
 
270
271
  test "collection check box generates only one hidden field for the entire collection, to ensure something will be sent back to the server when posting an empty collection" do
271
272
  collection = [Tag.new(1, 'Tag 1'), Tag.new(2, 'Tag 2')]
272
273
  with_collection_check_boxes @user, :tag_ids, collection, :id, :name
273
274
 
274
- assert_select "form input[type=hidden][name='user[tag_ids][]'][value=]", count: 1
275
+ assert_select "form input[type=hidden][name='user[tag_ids][]'][value='']", count: 1
275
276
  end
276
277
 
277
278
  test "collection check box accepts a collection and generate a serie of checkboxes with labels for label method" do
@@ -283,13 +284,13 @@ class BuilderTest < ActionView::TestCase
283
284
  end
284
285
 
285
286
  test "collection check box handles camelized collection values for labels correctly" do
286
- with_collection_check_boxes @user, :active, ['Yes', 'No'], :to_s, :to_s
287
+ with_collection_check_boxes @user, :active, %w[Yes No], :to_s, :to_s
287
288
 
288
289
  assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
289
290
  assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
290
291
  end
291
292
 
292
- test "collection check box should sanitize collection values for labels correctly" do
293
+ test "collection check box sanitizes collection values for labels correctly" do
293
294
  with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
294
295
  assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
295
296
  assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
@@ -301,36 +302,36 @@ class BuilderTest < ActionView::TestCase
301
302
 
302
303
  with_collection_check_boxes user, :tag_ids, collection, :first, :last
303
304
 
304
- assert_select 'form input[type=checkbox][value=1][checked=checked]'
305
- assert_select 'form input[type=checkbox][value=3][checked=checked]'
306
- assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
305
+ assert_select 'form input[type=checkbox][value="1"][checked=checked]'
306
+ assert_select 'form input[type=checkbox][value="3"][checked=checked]'
307
+ assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
307
308
  end
308
309
 
309
310
  test "collection check box accepts selected values as :checked option" do
310
311
  collection = (1..3).map { |i| [i, "Tag #{i}"] }
311
312
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, checked: [1, 3]
312
313
 
313
- assert_select 'form input[type=checkbox][value=1][checked=checked]'
314
- assert_select 'form input[type=checkbox][value=3][checked=checked]'
315
- assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
314
+ assert_select 'form input[type=checkbox][value="1"][checked=checked]'
315
+ assert_select 'form input[type=checkbox][value="3"][checked=checked]'
316
+ assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
316
317
  end
317
318
 
318
319
  test "collection check boxes accepts selected string values as :checked option" do
319
320
  collection = (1..3).map { |i| [i, "Category #{i}"] }
320
- with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: ['1', '3']
321
+ with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: %w[1 3]
321
322
 
322
- assert_select 'input[type=checkbox][value=1][checked=checked]'
323
- assert_select 'input[type=checkbox][value=3][checked=checked]'
324
- assert_no_select 'input[type=checkbox][value=2][checked=checked]'
323
+ assert_select 'input[type=checkbox][value="1"][checked=checked]'
324
+ assert_select 'input[type=checkbox][value="3"][checked=checked]'
325
+ assert_no_select 'input[type=checkbox][value="2"][checked=checked]'
325
326
  end
326
327
 
327
328
  test "collection check box accepts a single checked value" do
328
329
  collection = (1..3).map { |i| [i, "Tag #{i}"] }
329
330
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, checked: 3
330
331
 
331
- assert_select 'form input[type=checkbox][value=3][checked=checked]'
332
- assert_no_select 'form input[type=checkbox][value=1][checked=checked]'
333
- assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
332
+ assert_select 'form input[type=checkbox][value="3"][checked=checked]'
333
+ assert_no_select 'form input[type=checkbox][value="1"][checked=checked]'
334
+ assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
334
335
  end
335
336
 
336
337
  test "collection check box accepts selected values as :checked option and override the model values" do
@@ -338,44 +339,44 @@ class BuilderTest < ActionView::TestCase
338
339
  @user.tag_ids = [2]
339
340
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, checked: [1, 3]
340
341
 
341
- assert_select 'form input[type=checkbox][value=1][checked=checked]'
342
- assert_select 'form input[type=checkbox][value=3][checked=checked]'
343
- assert_no_select 'form input[type=checkbox][value=2][checked=checked]'
342
+ assert_select 'form input[type=checkbox][value="1"][checked=checked]'
343
+ assert_select 'form input[type=checkbox][value="3"][checked=checked]'
344
+ assert_no_select 'form input[type=checkbox][value="2"][checked=checked]'
344
345
  end
345
346
 
346
347
  test "collection check box accepts multiple disabled items" do
347
348
  collection = (1..3).map { |i| [i, "Tag #{i}"] }
348
349
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, disabled: [1, 3]
349
350
 
350
- assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
351
- assert_select 'form input[type=checkbox][value=3][disabled=disabled]'
352
- assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
351
+ assert_select 'form input[type=checkbox][value="1"][disabled=disabled]'
352
+ assert_select 'form input[type=checkbox][value="3"][disabled=disabled]'
353
+ assert_no_select 'form input[type=checkbox][value="2"][disabled=disabled]'
353
354
  end
354
355
 
355
356
  test "collection check box accepts single disable item" do
356
357
  collection = (1..3).map { |i| [i, "Tag #{i}"] }
357
358
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, disabled: 1
358
359
 
359
- assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
360
- assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
361
- assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
360
+ assert_select 'form input[type=checkbox][value="1"][disabled=disabled]'
361
+ assert_no_select 'form input[type=checkbox][value="3"][disabled=disabled]'
362
+ assert_no_select 'form input[type=checkbox][value="2"][disabled=disabled]'
362
363
  end
363
364
 
364
365
  test "collection check box accepts a proc to disabled items" do
365
366
  collection = (1..3).map { |i| [i, "Tag #{i}"] }
366
367
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, disabled: proc { |i| i.first == 1 }
367
368
 
368
- assert_select 'form input[type=checkbox][value=1][disabled=disabled]'
369
- assert_no_select 'form input[type=checkbox][value=3][disabled=disabled]'
370
- assert_no_select 'form input[type=checkbox][value=2][disabled=disabled]'
369
+ assert_select 'form input[type=checkbox][value="1"][disabled=disabled]'
370
+ assert_no_select 'form input[type=checkbox][value="3"][disabled=disabled]'
371
+ assert_no_select 'form input[type=checkbox][value="2"][disabled=disabled]'
371
372
  end
372
373
 
373
374
  test "collection check box accepts html options" do
374
375
  collection = [[1, 'Tag 1'], [2, 'Tag 2']]
375
376
  with_collection_check_boxes @user, :tag_ids, collection, :first, :last, {}, class: 'check'
376
377
 
377
- assert_select 'form input.check[type=checkbox][value=1]'
378
- assert_select 'form input.check[type=checkbox][value=2]'
378
+ assert_select 'form input.check[type=checkbox][value="1"]'
379
+ assert_select 'form input.check[type=checkbox][value="2"]'
379
380
  end
380
381
 
381
382
  test "collection check box with fields for" do
@@ -386,8 +387,8 @@ class BuilderTest < ActionView::TestCase
386
387
  end
387
388
  end
388
389
 
389
- assert_select 'form input#user_post_tag_ids_1[type=checkbox][value=1]'
390
- assert_select 'form input#user_post_tag_ids_2[type=checkbox][value=2]'
390
+ assert_select 'form input#user_post_tag_ids_1[type=checkbox][value="1"]'
391
+ assert_select 'form input#user_post_tag_ids_2[type=checkbox][value="2"]'
391
392
 
392
393
  assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_1]', 'Tag 1'
393
394
  assert_select 'form label.collection_check_boxes[for=user_post_tag_ids_2]', 'Tag 2'
@@ -541,7 +542,7 @@ class BuilderTest < ActionView::TestCase
541
542
 
542
543
  test "collection check boxes with block helpers does not leak the template" do
543
544
  with_concat_form_for(@user) do |f|
544
- collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
545
+ collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
545
546
  b.label(class: b.object) { b.check_box + b.text }
546
547
  end
547
548
  concat collection_input
@@ -593,7 +594,7 @@ class BuilderTest < ActionView::TestCase
593
594
  end
594
595
  end
595
596
 
596
- test "fields inherites wrapper option from the parent form" do
597
+ test "fields inherits wrapper option from the parent form" do
597
598
  swap_wrapper :another do
598
599
  simple_form_for(:user, wrapper: :another) do |f|
599
600
  f.simple_fields_for(:company) do |company|