simple_form 3.4.0 → 5.1.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 (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