simple_form 3.4.0 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +118 -8
  3. data/MIT-LICENSE +2 -1
  4. data/README.md +235 -67
  5. data/lib/generators/simple_form/install_generator.rb +1 -0
  6. data/lib/generators/simple_form/templates/README +2 -3
  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 +14 -7
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +360 -74
  12. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +20 -8
  13. data/lib/simple_form/action_view_extensions/builder.rb +1 -0
  14. data/lib/simple_form/action_view_extensions/form_helper.rb +1 -0
  15. data/lib/simple_form/components/errors.rb +15 -2
  16. data/lib/simple_form/components/hints.rb +1 -0
  17. data/lib/simple_form/components/html5.rb +1 -0
  18. data/lib/simple_form/components/label_input.rb +2 -1
  19. data/lib/simple_form/components/labels.rb +12 -7
  20. data/lib/simple_form/components/maxlength.rb +4 -17
  21. data/lib/simple_form/components/min_max.rb +1 -0
  22. data/lib/simple_form/components/minlength.rb +5 -18
  23. data/lib/simple_form/components/pattern.rb +1 -0
  24. data/lib/simple_form/components/placeholders.rb +2 -1
  25. data/lib/simple_form/components/readonly.rb +1 -0
  26. data/lib/simple_form/components.rb +1 -0
  27. data/lib/simple_form/error_notification.rb +1 -0
  28. data/lib/simple_form/form_builder.rb +104 -29
  29. data/lib/simple_form/helpers/autofocus.rb +1 -0
  30. data/lib/simple_form/helpers/disabled.rb +1 -0
  31. data/lib/simple_form/helpers/readonly.rb +1 -0
  32. data/lib/simple_form/helpers/required.rb +1 -0
  33. data/lib/simple_form/helpers/validators.rb +2 -1
  34. data/lib/simple_form/helpers.rb +1 -0
  35. data/lib/simple_form/inputs/base.rb +24 -5
  36. data/lib/simple_form/inputs/block_input.rb +1 -0
  37. data/lib/simple_form/inputs/boolean_input.rb +4 -2
  38. data/lib/simple_form/inputs/collection_check_boxes_input.rb +3 -2
  39. data/lib/simple_form/inputs/collection_input.rb +6 -7
  40. data/lib/simple_form/inputs/collection_radio_buttons_input.rb +2 -1
  41. data/lib/simple_form/inputs/collection_select_input.rb +1 -0
  42. data/lib/simple_form/inputs/color_input.rb +14 -0
  43. data/lib/simple_form/inputs/date_time_input.rb +1 -0
  44. data/lib/simple_form/inputs/file_input.rb +1 -0
  45. data/lib/simple_form/inputs/grouped_collection_select_input.rb +1 -0
  46. data/lib/simple_form/inputs/hidden_input.rb +1 -0
  47. data/lib/simple_form/inputs/numeric_input.rb +1 -0
  48. data/lib/simple_form/inputs/password_input.rb +1 -0
  49. data/lib/simple_form/inputs/priority_input.rb +1 -4
  50. data/lib/simple_form/inputs/range_input.rb +1 -0
  51. data/lib/simple_form/inputs/rich_text_area_input.rb +12 -0
  52. data/lib/simple_form/inputs/string_input.rb +2 -1
  53. data/lib/simple_form/inputs/text_input.rb +1 -0
  54. data/lib/simple_form/inputs.rb +3 -0
  55. data/lib/simple_form/map_type.rb +1 -0
  56. data/lib/simple_form/railtie.rb +1 -0
  57. data/lib/simple_form/tags.rb +7 -2
  58. data/lib/simple_form/version.rb +2 -1
  59. data/lib/simple_form/wrappers/builder.rb +1 -0
  60. data/lib/simple_form/wrappers/leaf.rb +2 -1
  61. data/lib/simple_form/wrappers/many.rb +1 -0
  62. data/lib/simple_form/wrappers/root.rb +9 -2
  63. data/lib/simple_form/wrappers/single.rb +2 -1
  64. data/lib/simple_form/wrappers.rb +1 -0
  65. data/lib/simple_form.rb +79 -11
  66. data/test/action_view_extensions/builder_test.rb +28 -9
  67. data/test/action_view_extensions/form_helper_test.rb +3 -2
  68. data/test/components/custom_components_test.rb +62 -0
  69. data/test/components/label_test.rb +33 -8
  70. data/test/form_builder/association_test.rb +33 -2
  71. data/test/form_builder/button_test.rb +1 -0
  72. data/test/form_builder/error_notification_test.rb +1 -0
  73. data/test/form_builder/error_test.rb +12 -0
  74. data/test/form_builder/general_test.rb +75 -13
  75. data/test/form_builder/hint_test.rb +6 -0
  76. data/test/form_builder/input_field_test.rb +30 -10
  77. data/test/form_builder/label_test.rb +10 -4
  78. data/test/form_builder/wrapper_test.rb +32 -5
  79. data/test/generators/simple_form_generator_test.rb +4 -3
  80. data/test/inputs/boolean_input_test.rb +17 -0
  81. data/test/inputs/collection_check_boxes_input_test.rb +38 -18
  82. data/test/inputs/collection_radio_buttons_input_test.rb +48 -28
  83. data/test/inputs/collection_select_input_test.rb +46 -43
  84. data/test/inputs/color_input_test.rb +10 -0
  85. data/test/inputs/datetime_input_test.rb +7 -16
  86. data/test/inputs/disabled_test.rb +14 -0
  87. data/test/inputs/discovery_test.rb +22 -0
  88. data/test/inputs/file_input_test.rb +1 -0
  89. data/test/inputs/general_test.rb +3 -2
  90. data/test/inputs/grouped_collection_select_input_test.rb +11 -10
  91. data/test/inputs/hidden_input_test.rb +1 -0
  92. data/test/inputs/numeric_input_test.rb +2 -1
  93. data/test/inputs/priority_input_test.rb +7 -14
  94. data/test/inputs/readonly_test.rb +1 -0
  95. data/test/inputs/required_test.rb +1 -0
  96. data/test/inputs/rich_text_area_input_test.rb +15 -0
  97. data/test/inputs/string_input_test.rb +10 -16
  98. data/test/inputs/text_input_test.rb +1 -0
  99. data/test/simple_form_test.rb +1 -0
  100. data/test/support/discovery_inputs.rb +8 -0
  101. data/test/support/misc_helpers.rb +22 -1
  102. data/test/support/mock_controller.rb +7 -1
  103. data/test/support/models.rb +80 -18
  104. data/test/test_helper.rb +9 -4
  105. metadata +49 -55
  106. data/lib/simple_form/i18n_cache.rb +0 -22
@@ -1,16 +1,17 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class CollectionCheckBoxesInput < CollectionRadioButtonsInput
4
5
  protected
5
6
 
6
7
  # Checkbox components do not use the required html tag.
7
- # More info: https://github.com/plataformatec/simple_form/issues/340#issuecomment-2871956
8
+ # More info: https://github.com/heartcombo/simple_form/issues/340#issuecomment-2871956
8
9
  def has_required?
9
10
  false
10
11
  end
11
12
 
12
13
  def build_nested_boolean_style_item_tag(collection_builder)
13
- collection_builder.check_box + collection_builder.text
14
+ collection_builder.check_box + collection_builder.text.to_s
14
15
  end
15
16
 
16
17
  def item_wrapper_class
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class CollectionInput < Base
@@ -9,10 +10,8 @@ module SimpleForm
9
10
  # Texts can be translated using i18n in "simple_form.yes" and
10
11
  # "simple_form.no" keys. See the example locale file.
11
12
  def self.boolean_collection
12
- i18n_cache :boolean_collection do
13
- [ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
14
- [I18n.t(:"simple_form.no", default: 'No'), false] ]
15
- end
13
+ [ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
14
+ [I18n.t(:"simple_form.no", default: 'No'), false] ]
16
15
  end
17
16
 
18
17
  def input(wrapper_options = nil)
@@ -40,12 +39,12 @@ module SimpleForm
40
39
  end
41
40
 
42
41
  def has_required?
43
- super && (input_options[:include_blank] || input_options[:prompt] || multiple?)
42
+ super && (input_options[:include_blank] || input_options[:prompt].present? || multiple?)
44
43
  end
45
44
 
46
45
  # Check if :include_blank must be included by default.
47
46
  def skip_include_blank?
48
- (options.keys & [:prompt, :include_blank, :default, :selected]).any? || multiple?
47
+ (options.keys & %i[prompt include_blank default selected]).any? || multiple?
49
48
  end
50
49
 
51
50
  def multiple?
@@ -89,7 +88,7 @@ module SimpleForm
89
88
  end
90
89
 
91
90
  def detect_collection_classes(some_collection = collection)
92
- some_collection.map { |e| e.class }.uniq
91
+ some_collection.map(&:class).uniq
93
92
  end
94
93
 
95
94
  def collection_includes_basic_objects?(collection_classes)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class CollectionRadioButtonsInput < CollectionInput
@@ -40,7 +41,7 @@ module SimpleForm
40
41
  end
41
42
 
42
43
  def build_nested_boolean_style_item_tag(collection_builder)
43
- collection_builder.radio_button + collection_builder.text
44
+ collection_builder.radio_button + collection_builder.text.to_s
44
45
  end
45
46
 
46
47
  def item_wrapper_class
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class CollectionSelectInput < CollectionInput
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Inputs
4
+ class ColorInput < Base
5
+ def input(wrapper_options = nil)
6
+ input_html_options[:type] ||= "color" if html5?
7
+
8
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
9
+
10
+ @builder.text_field(attribute_name, merged_input_options)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class DateTimeInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class FileInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class GroupedCollectionSelectInput < CollectionInput
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class HiddenInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class NumericInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class PasswordInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class PriorityInput < CollectionSelectInput
@@ -14,10 +15,6 @@ module SimpleForm
14
15
 
15
16
  protected
16
17
 
17
- def has_required?
18
- false
19
- end
20
-
21
18
  def skip_include_blank?
22
19
  super || input_priority.present?
23
20
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class RangeInput < NumericInput
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Inputs
4
+ class RichTextAreaInput < Base
5
+ def input(wrapper_options = nil)
6
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
7
+
8
+ @builder.rich_text_area(attribute_name, merged_input_options)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class StringInput < Base
@@ -17,7 +18,7 @@ module SimpleForm
17
18
  private
18
19
 
19
20
  def string?
20
- input_type == :string
21
+ input_type == :string || input_type == :citext
21
22
  end
22
23
  end
23
24
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class TextInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  extend ActiveSupport::Autoload
@@ -9,6 +10,7 @@ module SimpleForm
9
10
  autoload :CollectionInput
10
11
  autoload :CollectionRadioButtonsInput
11
12
  autoload :CollectionSelectInput
13
+ autoload :ColorInput
12
14
  autoload :DateTimeInput
13
15
  autoload :FileInput
14
16
  autoload :GroupedCollectionSelectInput
@@ -17,6 +19,7 @@ module SimpleForm
17
19
  autoload :PasswordInput
18
20
  autoload :PriorityInput
19
21
  autoload :RangeInput
22
+ autoload :RichTextAreaInput
20
23
  autoload :StringInput
21
24
  autoload :TextInput
22
25
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support/core_ext/class/attribute'
2
3
 
3
4
  module SimpleForm
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'rails/railtie'
2
3
 
3
4
  module SimpleForm
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Tags
3
4
  module CollectionExtensions
@@ -47,7 +48,9 @@ module SimpleForm
47
48
  private
48
49
 
49
50
  def render_component(builder)
50
- builder.radio_button + builder.label(class: "collection_radio_buttons")
51
+ label_class = "#{@options[:item_label_class]} collection_radio_buttons".strip
52
+
53
+ builder.radio_button + builder.label(class: label_class)
51
54
  end
52
55
  end
53
56
 
@@ -61,7 +64,9 @@ module SimpleForm
61
64
  private
62
65
 
63
66
  def render_component(builder)
64
- builder.check_box + builder.label(class: "collection_check_boxes")
67
+ label_class = "#{@options[:item_label_class]} collection_check_boxes".strip
68
+
69
+ builder.check_box + builder.label(class: label_class)
65
70
  end
66
71
  end
67
72
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
- VERSION = "3.4.0".freeze
3
+ VERSION = "5.1.0".freeze
3
4
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  # Provides the builder syntax for components. The builder provides
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  class Leaf
@@ -11,7 +12,7 @@ module SimpleForm
11
12
  def render(input)
12
13
  method = input.method(@namespace)
13
14
 
14
- if method.arity == 0
15
+ if method.arity.zero?
15
16
  ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: @namespace })
16
17
 
17
18
  method.call
@@ -1,3 +1,4 @@
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.
@@ -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
@@ -27,10 +28,16 @@ module SimpleForm
27
28
  css += SimpleForm.additional_classes_for(:wrapper) do
28
29
  input.additional_classes + [input.input_class]
29
30
  end
30
- css << (options[:wrapper_error_class] || @defaults[:error_class]) if input.has_errors?
31
- css << (options[:wrapper_hint_class] || @defaults[:hint_class]) if input.has_hint?
31
+ css << html_class(:error_class, options) { input.has_errors? }
32
+ css << html_class(:hint_class, options) { input.has_hint? }
33
+ css << html_class(:valid_class, options) { input.valid? }
32
34
  css.compact
33
35
  end
36
+
37
+ def html_class(key, options)
38
+ css = (options[:"wrapper_#{key}"] || @defaults[key])
39
+ css if css && yield
40
+ end
34
41
  end
35
42
  end
36
43
  end
@@ -1,3 +1,4 @@
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.
@@ -19,7 +20,7 @@ module SimpleForm
19
20
  private
20
21
 
21
22
  def html_options(options)
22
- [:label, :input].include?(namespace) ? {} : super
23
+ %i[label input].include?(namespace) ? {} : super
23
24
  end
24
25
  end
25
26
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Wrappers
3
4
  autoload :Builder, 'simple_form/wrappers/builder'
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'
@@ -33,7 +35,18 @@ to
33
35
 
34
36
  def %{name}(wrapper_options)
35
37
 
36
- See https://github.com/plataformatec/simple_form/pull/997 for more information.
38
+ See https://github.com/heartcombo/simple_form/pull/997 for more information.
39
+ WARN
40
+
41
+ FILE_METHODS_DEPRECATION_WARN = <<-WARN
42
+ [SIMPLE_FORM] SimpleForm.file_methods is deprecated and has no effect.
43
+
44
+ Since version 5, Simple Form now supports automatically discover of file inputs for the following Gems: activestorage, carrierwave, paperclip, refile and shrine.
45
+ If you are using a custom method that is not from one of the supported Gems, please change your forms to pass the input type explicitly:
46
+
47
+ <%= form.input :avatar, as: :file %>
48
+
49
+ See http://blog.plataformatec.com.br/2019/09/incorrect-access-control-in-simple-form-cve-2019-16676 for more information.
37
50
  WARN
38
51
 
39
52
  @@configured = false
@@ -58,11 +71,11 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
58
71
 
59
72
  # Series of attemps to detect a default label method for collection.
60
73
  mattr_accessor :collection_label_methods
61
- @@collection_label_methods = [:to_label, :name, :title, :to_s]
74
+ @@collection_label_methods = %i[to_label name title to_s]
62
75
 
63
76
  # Series of attemps to detect a default value method for collection.
64
77
  mattr_accessor :collection_value_methods
65
- @@collection_value_methods = [:id, :to_s]
78
+ @@collection_value_methods = %i[id to_s]
66
79
 
67
80
  # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
68
81
  mattr_accessor :collection_wrapper_tag
@@ -84,7 +97,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
84
97
 
85
98
  # How the label text should be generated altogether with the required text.
86
99
  mattr_accessor :label_text
87
- @@label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
100
+ @@label_text = ->(label, required, explicit_label) { "#{required} #{label}" }
88
101
 
89
102
  # You can define the class to be used on all labels. Defaults to none.
90
103
  mattr_accessor :label_class
@@ -108,7 +121,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
108
121
 
109
122
  # You can define which elements should obtain additional classes.
110
123
  mattr_accessor :generate_additional_classes_for
111
- @@generate_additional_classes_for = [:wrapper, :label, :input]
124
+ @@generate_additional_classes_for = %i[wrapper label input]
112
125
 
113
126
  # Whether attributes are required by default or not.
114
127
  mattr_accessor :required_by_default
@@ -118,10 +131,6 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
118
131
  mattr_accessor :browser_validations
119
132
  @@browser_validations = true
120
133
 
121
- # Collection of methods to detect if a file type was given.
122
- mattr_accessor :file_methods
123
- @@file_methods = [:mounted_as, :file?, :public_filename]
124
-
125
134
  # Custom mappings for input types. This should be a hash containing a regexp
126
135
  # to match as key, and the input type that will be used when the field name
127
136
  # matches the regexp as value, such as { /count/ => :integer }.
@@ -163,7 +172,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
163
172
 
164
173
  # Cache SimpleForm inputs discovery.
165
174
  mattr_accessor :cache_discovery
166
- @@cache_discovery = defined?(Rails) && !Rails.env.development?
175
+ @@cache_discovery = defined?(Rails.env) && !Rails.env.development?
167
176
 
168
177
  # Adds a class to each generated button, mostly for compatiblity.
169
178
  mattr_accessor :button_class
@@ -198,6 +207,12 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
198
207
  mattr_accessor :i18n_scope
199
208
  @@i18n_scope = 'simple_form'
200
209
 
210
+ mattr_accessor :input_field_error_class
211
+ @@input_field_error_class = nil
212
+
213
+ mattr_accessor :input_field_valid_class
214
+ @@input_field_valid_class = nil
215
+
201
216
  # Retrieves a given wrapper
202
217
  def self.wrapper(name)
203
218
  @@wrappers[name.to_s] or raise WrapperNotFound, "Couldn't find wrapper with name #{name}"
@@ -227,7 +242,7 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
227
242
  SimpleForm::Wrappers::Root.new(builder.to_a, options)
228
243
  end
229
244
 
230
- wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors do |b|
245
+ wrappers class: :input, hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
231
246
  b.use :html5
232
247
 
233
248
  b.use :min_max
@@ -257,12 +272,65 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
257
272
  @@form_class = value
258
273
  end
259
274
 
275
+ def self.file_methods=(file_methods)
276
+ ActiveSupport::Deprecation.warn(FILE_METHODS_DEPRECATION_WARN, caller)
277
+ @@file_methods = file_methods
278
+ end
279
+
280
+ def self.file_methods
281
+ ActiveSupport::Deprecation.warn(FILE_METHODS_DEPRECATION_WARN, caller)
282
+ @@file_methods
283
+ end
284
+
260
285
  # Default way to setup Simple Form. Run rails generate simple_form:install
261
286
  # to create a fresh initializer with all configuration values.
262
287
  def self.setup
263
288
  @@configured = true
264
289
  yield self
265
290
  end
291
+
292
+ # Includes a component to be used by Simple Form. Methods defined in a
293
+ # component will be exposed to be used in the wrapper as Simple::Components
294
+ #
295
+ # Examples
296
+ #
297
+ # # The application needs to tell where the components will be.
298
+ # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
299
+ #
300
+ # # Create a custom component in the path specified above.
301
+ # # lib/components/input_group_component.rb
302
+ # module InputGroupComponent
303
+ # def prepend
304
+ # ...
305
+ # end
306
+ #
307
+ # def append
308
+ # ...
309
+ # end
310
+ # end
311
+ #
312
+ # SimpleForm.setup do |config|
313
+ # # Create a wrapper using the custom component.
314
+ # config.wrappers :input_group, tag: :div, error_class: :error do |b|
315
+ # b.use :label
316
+ # b.optional :prepend
317
+ # b.use :input
318
+ # b.use :append
319
+ # end
320
+ # end
321
+ #
322
+ # # Using the custom component in the form.
323
+ # <%= simple_form_for @blog, wrapper: input_group do |f| %>
324
+ # <%= f.input :title, prepend: true %>
325
+ # <% end %>
326
+ #
327
+ def self.include_component(component)
328
+ if Module === component
329
+ SimpleForm::Inputs::Base.include(component)
330
+ else
331
+ raise TypeError, "SimpleForm.include_component expects a module but got: #{component.class}"
332
+ end
333
+ end
266
334
  end
267
335
 
268
336
  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
@@ -36,7 +37,7 @@ 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'
@@ -44,8 +45,17 @@ class BuilderTest < ActionView::TestCase
44
45
 
45
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
- assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
48
- assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
48
+
49
+ # Rails 6 changed the way it sanitizes the values
50
+ # https://github.com/rails/rails/blob/6-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
51
+ # https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
52
+ if ActionView::VERSION::MAJOR == 5
53
+ assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
54
+ assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
55
+ else
56
+ assert_select 'label.collection_radio_buttons[for=user_name_0_99]', '$0.99'
57
+ assert_select 'label.collection_radio_buttons[for=user_name_1_99]', '$1.99'
58
+ end
49
59
  end
50
60
 
51
61
  test "collection radio checks the correct value to local variables" do
@@ -243,7 +253,7 @@ class BuilderTest < ActionView::TestCase
243
253
 
244
254
  test "collection radio with block helpers does not leak the template" do
245
255
  with_concat_form_for(@user) do |f|
246
- collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
256
+ collection_input = f.collection_radio_buttons :active, [true, false], :to_s, :to_s do |b|
247
257
  b.label(class: b.object) { b.radio_button + b.text }
248
258
  end
249
259
  concat collection_input
@@ -283,7 +293,7 @@ class BuilderTest < ActionView::TestCase
283
293
  end
284
294
 
285
295
  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
296
+ with_collection_check_boxes @user, :active, %w[Yes No], :to_s, :to_s
287
297
 
288
298
  assert_select 'form label.collection_check_boxes[for=user_active_yes]', 'Yes'
289
299
  assert_select 'form label.collection_check_boxes[for=user_active_no]', 'No'
@@ -291,8 +301,17 @@ class BuilderTest < ActionView::TestCase
291
301
 
292
302
  test "collection check box sanitizes collection values for labels correctly" do
293
303
  with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
294
- assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
295
- assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
304
+
305
+ # Rails 6 changed the way it sanitizes the values
306
+ # https://github.com/rails/rails/blob/6-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
307
+ # https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
308
+ if ActionView::VERSION::MAJOR == 5
309
+ assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
310
+ assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
311
+ else
312
+ assert_select 'label.collection_check_boxes[for=user_name_0_99]', '$0.99'
313
+ assert_select 'label.collection_check_boxes[for=user_name_1_99]', '$1.99'
314
+ end
296
315
  end
297
316
 
298
317
  test "collection check box checks the correct value to local variables" do
@@ -317,7 +336,7 @@ class BuilderTest < ActionView::TestCase
317
336
 
318
337
  test "collection check boxes accepts selected string values as :checked option" do
319
338
  collection = (1..3).map { |i| [i, "Category #{i}"] }
320
- with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: ['1', '3']
339
+ with_collection_check_boxes :user, :category_ids, collection, :first, :last, checked: %w[1 3]
321
340
 
322
341
  assert_select 'input[type=checkbox][value="1"][checked=checked]'
323
342
  assert_select 'input[type=checkbox][value="3"][checked=checked]'
@@ -541,7 +560,7 @@ class BuilderTest < ActionView::TestCase
541
560
 
542
561
  test "collection check boxes with block helpers does not leak the template" do
543
562
  with_concat_form_for(@user) do |f|
544
- collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
563
+ collection_input = f.collection_check_boxes :active, [true, false], :to_s, :to_s do |b|
545
564
  b.label(class: b.object) { b.check_box + b.text }
546
565
  end
547
566
  concat collection_input
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  class FormHelperTest < ActionView::TestCase
@@ -151,7 +152,7 @@ class FormHelperTest < ActionView::TestCase
151
152
  end
152
153
 
153
154
  test 'SimpleForm for swaps default action view field_error_proc' do
154
- expected_error_proc = lambda {}
155
+ expected_error_proc = -> {}
155
156
  swap SimpleForm, field_error_proc: expected_error_proc do
156
157
  simple_form_for :user do |f|
157
158
  assert_equal expected_error_proc, ::ActionView::Base.field_error_proc
@@ -161,7 +162,7 @@ class FormHelperTest < ActionView::TestCase
161
162
 
162
163
  private
163
164
 
164
- def swap_field_error_proc(expected_error_proc = lambda {})
165
+ def swap_field_error_proc(expected_error_proc = -> {})
165
166
  swap ActionView::Base, field_error_proc: expected_error_proc do
166
167
  yield
167
168