simple_form 3.4.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of simple_form might be problematic. Click here for more details.

Files changed (103) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +62 -0
  3. data/README.md +208 -36
  4. data/lib/generators/simple_form/install_generator.rb +1 -0
  5. data/lib/generators/simple_form/templates/README +3 -3
  6. data/lib/generators/simple_form/templates/_form.html.erb +2 -0
  7. data/lib/generators/simple_form/templates/_form.html.haml +2 -0
  8. data/lib/generators/simple_form/templates/_form.html.slim +1 -0
  9. data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +15 -5
  10. data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +358 -73
  11. data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +20 -8
  12. data/lib/simple_form/action_view_extensions/builder.rb +1 -0
  13. data/lib/simple_form/action_view_extensions/form_helper.rb +1 -0
  14. data/lib/simple_form/components/errors.rb +15 -2
  15. data/lib/simple_form/components/hints.rb +1 -0
  16. data/lib/simple_form/components/html5.rb +1 -0
  17. data/lib/simple_form/components/label_input.rb +2 -1
  18. data/lib/simple_form/components/labels.rb +11 -4
  19. data/lib/simple_form/components/maxlength.rb +4 -13
  20. data/lib/simple_form/components/min_max.rb +1 -0
  21. data/lib/simple_form/components/minlength.rb +5 -14
  22. data/lib/simple_form/components/pattern.rb +1 -0
  23. data/lib/simple_form/components/placeholders.rb +2 -1
  24. data/lib/simple_form/components/readonly.rb +1 -0
  25. data/lib/simple_form/components.rb +1 -0
  26. data/lib/simple_form/error_notification.rb +1 -0
  27. data/lib/simple_form/form_builder.rb +81 -26
  28. data/lib/simple_form/helpers/autofocus.rb +1 -0
  29. data/lib/simple_form/helpers/disabled.rb +1 -0
  30. data/lib/simple_form/helpers/readonly.rb +1 -0
  31. data/lib/simple_form/helpers/required.rb +1 -0
  32. data/lib/simple_form/helpers/validators.rb +2 -1
  33. data/lib/simple_form/helpers.rb +1 -0
  34. data/lib/simple_form/i18n_cache.rb +1 -0
  35. data/lib/simple_form/inputs/base.rb +24 -2
  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 +2 -1
  39. data/lib/simple_form/inputs/collection_input.rb +3 -2
  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 -0
  50. data/lib/simple_form/inputs/range_input.rb +1 -0
  51. data/lib/simple_form/inputs/string_input.rb +2 -1
  52. data/lib/simple_form/inputs/text_input.rb +1 -0
  53. data/lib/simple_form/inputs.rb +2 -0
  54. data/lib/simple_form/map_type.rb +1 -0
  55. data/lib/simple_form/railtie.rb +1 -0
  56. data/lib/simple_form/tags.rb +1 -0
  57. data/lib/simple_form/version.rb +2 -1
  58. data/lib/simple_form/wrappers/builder.rb +1 -0
  59. data/lib/simple_form/wrappers/leaf.rb +2 -1
  60. data/lib/simple_form/wrappers/many.rb +1 -0
  61. data/lib/simple_form/wrappers/root.rb +2 -0
  62. data/lib/simple_form/wrappers/single.rb +2 -1
  63. data/lib/simple_form/wrappers.rb +1 -0
  64. data/lib/simple_form.rb +58 -7
  65. data/test/action_view_extensions/builder_test.rb +6 -5
  66. data/test/action_view_extensions/form_helper_test.rb +3 -2
  67. data/test/components/custom_components_test.rb +62 -0
  68. data/test/components/label_test.rb +33 -4
  69. data/test/form_builder/association_test.rb +27 -2
  70. data/test/form_builder/button_test.rb +1 -0
  71. data/test/form_builder/error_notification_test.rb +1 -0
  72. data/test/form_builder/error_test.rb +12 -0
  73. data/test/form_builder/general_test.rb +67 -3
  74. data/test/form_builder/hint_test.rb +6 -0
  75. data/test/form_builder/input_field_test.rb +30 -10
  76. data/test/form_builder/label_test.rb +9 -3
  77. data/test/form_builder/wrapper_test.rb +24 -4
  78. data/test/generators/simple_form_generator_test.rb +4 -3
  79. data/test/inputs/boolean_input_test.rb +17 -0
  80. data/test/inputs/collection_check_boxes_input_test.rb +30 -14
  81. data/test/inputs/collection_radio_buttons_input_test.rb +40 -24
  82. data/test/inputs/collection_select_input_test.rb +40 -39
  83. data/test/inputs/color_input_test.rb +10 -0
  84. data/test/inputs/datetime_input_test.rb +7 -16
  85. data/test/inputs/disabled_test.rb +14 -0
  86. data/test/inputs/discovery_test.rb +22 -0
  87. data/test/inputs/file_input_test.rb +1 -0
  88. data/test/inputs/general_test.rb +3 -2
  89. data/test/inputs/grouped_collection_select_input_test.rb +11 -10
  90. data/test/inputs/hidden_input_test.rb +1 -0
  91. data/test/inputs/numeric_input_test.rb +2 -1
  92. data/test/inputs/priority_input_test.rb +3 -10
  93. data/test/inputs/readonly_test.rb +1 -0
  94. data/test/inputs/required_test.rb +1 -0
  95. data/test/inputs/string_input_test.rb +10 -16
  96. data/test/inputs/text_input_test.rb +1 -0
  97. data/test/simple_form_test.rb +1 -0
  98. data/test/support/discovery_inputs.rb +8 -0
  99. data/test/support/misc_helpers.rb +22 -1
  100. data/test/support/mock_controller.rb +7 -1
  101. data/test/support/models.rb +52 -16
  102. data/test/test_helper.rb +2 -0
  103. metadata +40 -47
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  module HTML5
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  module LabelInput
@@ -20,7 +21,7 @@ module SimpleForm
20
21
  def deprecated_component(namespace, wrapper_options)
21
22
  method = method(namespace)
22
23
 
23
- if method.arity == 0
24
+ if method.arity.zero?
24
25
  ActiveSupport::Deprecation.warn(SimpleForm::CUSTOM_INPUT_DEPRECATION_WARN % { name: namespace })
25
26
 
26
27
  method.call
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  module Labels
@@ -6,18 +7,24 @@ module SimpleForm
6
7
  module ClassMethods #:nodoc:
7
8
  def translate_required_html
8
9
  i18n_cache :translate_required_html do
9
- I18n.t(:"simple_form.required.html", default:
10
- %[<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>]
10
+ I18n.t(:"required.html", scope: i18n_scope, default:
11
+ %(<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>)
11
12
  )
12
13
  end
13
14
  end
14
15
 
15
16
  def translate_required_text
16
- I18n.t(:"simple_form.required.text", default: 'required')
17
+ I18n.t(:"required.text", scope: i18n_scope, default: 'required')
17
18
  end
18
19
 
19
20
  def translate_required_mark
20
- I18n.t(:"simple_form.required.mark", default: '*')
21
+ I18n.t(:"required.mark", scope: i18n_scope, default: '*')
22
+ end
23
+
24
+ private
25
+
26
+ def i18n_scope
27
+ SimpleForm.i18n_scope
21
28
  end
22
29
  end
23
30
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  # Needs to be enabled in order to do automatic lookups.
@@ -27,19 +28,9 @@ module SimpleForm
27
28
  length_validator.options[:tokenizer]
28
29
  end
29
30
 
30
- # Use validation with tokenizer if version of Rails is less than 5,
31
- # if not validate without the tokenizer, if version is greater than Rails 4.
32
- if ActionPack::VERSION::STRING < '5'
33
- def maximum_length_value_from(length_validator)
34
- if length_validator && !has_tokenizer?(length_validator)
35
- length_validator.options[:is] || length_validator.options[:maximum]
36
- end
37
- end
38
- elsif ActionPack::VERSION::STRING >= '5'
39
- def maximum_length_value_from(length_validator)
40
- if length_validator
41
- length_validator.options[:is] || length_validator.options[:maximum]
42
- end
31
+ def maximum_length_value_from(length_validator)
32
+ if length_validator
33
+ length_validator.options[:is] || length_validator.options[:maximum]
43
34
  end
44
35
  end
45
36
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  module MinMax
@@ -1,9 +1,10 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  # Needs to be enabled in order to do automatic lookups.
4
5
  module Minlength
5
6
  def minlength(wrapper_options = nil)
6
- input_html_options[:minlength] ||= minimum_length_from_validation || limit
7
+ input_html_options[:minlength] ||= minimum_length_from_validation
7
8
  nil
8
9
  end
9
10
 
@@ -27,19 +28,9 @@ module SimpleForm
27
28
  length_validator.options[:tokenizer]
28
29
  end
29
30
 
30
- # Use validation with tokenizer if version of Rails is less than 5,
31
- # if not validate without the tokenizer, if version is greater than Rails 4.
32
- if ActionPack::VERSION::STRING < '5'
33
- def minimum_length_value_from(length_validator)
34
- if length_validator && !has_tokenizer?(length_validator)
35
- length_validator.options[:is] || length_validator.options[:minimum]
36
- end
37
- end
38
- elsif ActionPack::VERSION::STRING >= '5'
39
- def minimum_length_value_from(length_validator)
40
- if length_validator
41
- length_validator.options[:is] || length_validator.options[:minimum]
42
- end
31
+ def minimum_length_value_from(length_validator)
32
+ if length_validator
33
+ length_validator.options[:is] || length_validator.options[:minimum]
43
34
  end
44
35
  end
45
36
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  # Needs to be enabled in order to do automatic lookups.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  # Needs to be enabled in order to do automatic lookups.
@@ -7,7 +8,7 @@ module SimpleForm
7
8
  nil
8
9
  end
9
10
 
10
- def placeholder_text
11
+ def placeholder_text(wrapper_options = nil)
11
12
  placeholder = options[:placeholder]
12
13
  placeholder.is_a?(String) ? placeholder : translate_from_namespace(:placeholders)
13
14
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Components
3
4
  # Needs to be enabled in order to do automatic lookups.
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  # Components are a special type of helpers that can work on their own.
3
4
  # For example, by using a component, it will automatically change the
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  class ErrorNotification
3
4
  delegate :object, :object_name, :template, to: :@builder
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support/core_ext/object/deep_dup'
2
3
  require 'simple_form/map_type'
3
4
  require 'simple_form/tags'
@@ -12,25 +13,25 @@ module SimpleForm
12
13
  'update' => 'edit'
13
14
  }
14
15
 
15
- ATTRIBUTE_COMPONENTS = [:html5, :min_max, :maxlength, :minlength, :placeholder, :pattern, :readonly]
16
+ ATTRIBUTE_COMPONENTS = %i[html5 min_max maxlength minlength placeholder pattern readonly]
16
17
 
17
18
  extend MapType
18
19
  include SimpleForm::Inputs
19
20
 
20
- map_type :text, to: SimpleForm::Inputs::TextInput
21
- map_type :file, to: SimpleForm::Inputs::FileInput
22
- map_type :string, :email, :search, :tel, :url, :uuid, to: SimpleForm::Inputs::StringInput
23
- map_type :password, to: SimpleForm::Inputs::PasswordInput
24
- map_type :integer, :decimal, :float, to: SimpleForm::Inputs::NumericInput
25
- map_type :range, to: SimpleForm::Inputs::RangeInput
26
- map_type :check_boxes, to: SimpleForm::Inputs::CollectionCheckBoxesInput
27
- map_type :radio_buttons, to: SimpleForm::Inputs::CollectionRadioButtonsInput
28
- map_type :select, to: SimpleForm::Inputs::CollectionSelectInput
29
- map_type :grouped_select, to: SimpleForm::Inputs::GroupedCollectionSelectInput
30
- map_type :date, :time, :datetime, to: SimpleForm::Inputs::DateTimeInput
31
- map_type :country, :time_zone, to: SimpleForm::Inputs::PriorityInput
32
- map_type :boolean, to: SimpleForm::Inputs::BooleanInput
33
- map_type :hidden, to: SimpleForm::Inputs::HiddenInput
21
+ map_type :text, :hstore, :json, :jsonb, to: SimpleForm::Inputs::TextInput
22
+ map_type :file, to: SimpleForm::Inputs::FileInput
23
+ map_type :string, :email, :search, :tel, :url, :uuid, :citext, to: SimpleForm::Inputs::StringInput
24
+ map_type :password, to: SimpleForm::Inputs::PasswordInput
25
+ map_type :integer, :decimal, :float, to: SimpleForm::Inputs::NumericInput
26
+ map_type :range, to: SimpleForm::Inputs::RangeInput
27
+ map_type :check_boxes, to: SimpleForm::Inputs::CollectionCheckBoxesInput
28
+ map_type :radio_buttons, to: SimpleForm::Inputs::CollectionRadioButtonsInput
29
+ map_type :select, to: SimpleForm::Inputs::CollectionSelectInput
30
+ map_type :grouped_select, to: SimpleForm::Inputs::GroupedCollectionSelectInput
31
+ map_type :date, :time, :datetime, to: SimpleForm::Inputs::DateTimeInput
32
+ map_type :country, :time_zone, to: SimpleForm::Inputs::PriorityInput
33
+ map_type :boolean, to: SimpleForm::Inputs::BooleanInput
34
+ map_type :hidden, to: SimpleForm::Inputs::HiddenInput
34
35
 
35
36
  def self.discovery_cache
36
37
  @discovery_cache ||= {}
@@ -38,6 +39,7 @@ module SimpleForm
38
39
 
39
40
  def initialize(*) #:nodoc:
40
41
  super
42
+ @object = convert_to_model(@object)
41
43
  @defaults = options[:defaults]
42
44
  @wrapper = SimpleForm.wrapper(options[:wrapper] || SimpleForm.default_wrapper)
43
45
  end
@@ -136,16 +138,39 @@ module SimpleForm
136
138
  # <input class="string required" id="user_name" maxlength="100"
137
139
  # name="user[name]" type="text" value="Carlos" />
138
140
  #
141
+ # It also support validation classes once it is configured.
142
+ #
143
+ # # config/initializers/simple_form.rb
144
+ # SimpleForm.setup do |config|
145
+ # config.input_field_valid_class = 'is-valid'
146
+ # config.input_field_error_class = 'is-invalid'
147
+ # end
148
+ #
149
+ # simple_form_for @user do |f|
150
+ # f.input_field :name
151
+ # end
152
+ #
153
+ # When the validation happens, the input will be rendered with
154
+ # the class configured according to the validation:
155
+ #
156
+ # - when the input is valid:
157
+ #
158
+ # <input class="is-valid string required" id="user_name" value="Carlos" />
159
+ #
160
+ # - when the input is invalid:
161
+ #
162
+ # <input class="is-invalid string required" id="user_name" value="" />
163
+ #
139
164
  def input_field(attribute_name, options = {})
140
165
  components = (wrapper.components.map(&:namespace) & ATTRIBUTE_COMPONENTS)
141
166
 
142
167
  options = options.dup
143
- options[:input_html] = options.except(:as, :boolean_style, :collection, :label_method, :value_method, :prompt, *components)
168
+ options[:input_html] = options.except(:as, :boolean_style, :collection, :disabled, :label_method, :value_method, :prompt, *components)
144
169
  options = @defaults.deep_dup.deep_merge(options) if @defaults
145
170
 
146
171
  input = find_input(attribute_name, options)
147
172
  wrapper = find_wrapper(input.input_type, options)
148
- components = components.concat([:input]).map { |component| SimpleForm::Wrappers::Leaf.new(component) }
173
+ components = build_input_field_components(components.push(:input))
149
174
 
150
175
  SimpleForm::Wrappers::Root.new(components, wrapper.options.merge(wrapper: false)).render input
151
176
  end
@@ -461,13 +486,17 @@ module SimpleForm
461
486
  relation = reflection.klass.all
462
487
 
463
488
  if reflection.respond_to?(:scope) && reflection.scope
464
- relation = reflection.klass.instance_exec(&reflection.scope)
489
+ if reflection.scope.parameters.any?
490
+ relation = reflection.klass.instance_exec(object, &reflection.scope)
491
+ else
492
+ relation = reflection.klass.instance_exec(&reflection.scope)
493
+ end
465
494
  else
466
495
  order = reflection.options[:order]
467
496
  conditions = reflection.options[:conditions]
468
497
  conditions = object.instance_exec(&conditions) if conditions.respond_to?(:call)
469
498
 
470
- relation = relation.where(conditions)
499
+ relation = relation.where(conditions) if relation.respond_to?(:where)
471
500
  relation = relation.order(order) if relation.respond_to?(:order)
472
501
  end
473
502
 
@@ -521,14 +550,14 @@ module SimpleForm
521
550
  case input_type
522
551
  when :timestamp
523
552
  :datetime
524
- when :string, nil
553
+ when :string, :citext, nil
525
554
  case attribute_name.to_s
526
- when /password/ then :password
527
- when /time_zone/ then :time_zone
528
- when /country/ then :country
529
- when /email/ then :email
530
- when /phone/ then :tel
531
- when /url/ then :url
555
+ when /(?:\b|\W|_)password(?:\b|\W|_)/ then :password
556
+ when /(?:\b|\W|_)time_zone(?:\b|\W|_)/ then :time_zone
557
+ when /(?:\b|\W|_)country(?:\b|\W|_)/ then :country
558
+ when /(?:\b|\W|_)email(?:\b|\W|_)/ then :email
559
+ when /(?:\b|\W|_)phone(?:\b|\W|_)/ then :tel
560
+ when /(?:\b|\W|_)url(?:\b|\W|_)/ then :url
532
561
  else
533
562
  file_method?(attribute_name) ? :file : (input_type || :string)
534
563
  end
@@ -640,5 +669,31 @@ module SimpleForm
640
669
 
641
670
  nil
642
671
  end
672
+
673
+ def build_input_field_components(components)
674
+ components.map do |component|
675
+ if component == :input
676
+ SimpleForm::Wrappers::Leaf.new(component, build_input_field_options)
677
+ else
678
+ SimpleForm::Wrappers::Leaf.new(component)
679
+ end
680
+ end
681
+ end
682
+
683
+ def build_input_field_options
684
+ input_field_options = {}
685
+ valid_class = SimpleForm.input_field_valid_class
686
+ error_class = SimpleForm.input_field_error_class
687
+
688
+ if error_class.present?
689
+ input_field_options[:error_class] = error_class
690
+ end
691
+
692
+ if valid_class.present?
693
+ input_field_options[:valid_class] = valid_class
694
+ end
695
+
696
+ input_field_options
697
+ end
643
698
  end
644
699
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Helpers
3
4
  module Autofocus
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Helpers
3
4
  module Disabled
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Helpers
3
4
  module Readonly
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Helpers
3
4
  module Required
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Helpers
3
4
  module Validators
@@ -24,7 +25,7 @@ module SimpleForm
24
25
  end
25
26
 
26
27
  def action_validator_match?(validator)
27
- return true if !validator.options.include?(:on)
28
+ return true unless validator.options.include?(:on)
28
29
 
29
30
  case validator.options[:on]
30
31
  when :save
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  # Helpers are made of several helpers that cannot be turned on automatically.
3
4
  # For instance, disabled cannot be turned on automatically, it requires the
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  # A lot of configuration values are retrived from I18n,
3
4
  # like boolean collection, required string. This module provides
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'simple_form/i18n_cache'
2
3
  require 'active_support/core_ext/string/output_safety'
3
4
  require 'action_view/helpers'
@@ -71,7 +72,10 @@ module SimpleForm
71
72
  @html_classes = SimpleForm.additional_classes_for(:input) { additional_classes }
72
73
 
73
74
  @input_html_classes = @html_classes.dup
74
- if SimpleForm.input_class && !input_html_classes.empty?
75
+
76
+ input_html_classes = self.input_html_classes
77
+
78
+ if SimpleForm.input_class && input_html_classes.any?
75
79
  input_html_classes << SimpleForm.input_class
76
80
  end
77
81
 
@@ -95,7 +99,7 @@ module SimpleForm
95
99
  end
96
100
 
97
101
  def input_class
98
- "#{lookup_model_names.join("_")}_#{reflection_or_attribute_name}"
102
+ "#{lookup_model_names.join('_')}_#{reflection_or_attribute_name}"
99
103
  end
100
104
 
101
105
  private
@@ -190,6 +194,8 @@ module SimpleForm
190
194
 
191
195
  def merge_wrapper_options(options, wrapper_options)
192
196
  if wrapper_options
197
+ wrapper_options = set_input_classes(wrapper_options)
198
+
193
199
  wrapper_options.merge(options) do |key, oldval, newval|
194
200
  case key.to_s
195
201
  when "class"
@@ -205,6 +211,22 @@ module SimpleForm
205
211
  end
206
212
  end
207
213
 
214
+ def set_input_classes(wrapper_options)
215
+ wrapper_options = wrapper_options.dup
216
+ error_class = wrapper_options.delete(:error_class)
217
+ valid_class = wrapper_options.delete(:valid_class)
218
+
219
+ if error_class.present? && has_errors?
220
+ wrapper_options[:class] = "#{wrapper_options[:class]} #{error_class}"
221
+ end
222
+
223
+ if valid_class.present? && valid?
224
+ wrapper_options[:class] = "#{wrapper_options[:class]} #{valid_class}"
225
+ end
226
+
227
+ wrapper_options
228
+ end
229
+
208
230
  def i18n_scope
209
231
  SimpleForm.i18n_scope
210
232
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class BlockInput < Base
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class BooleanInput < Base
@@ -59,9 +60,10 @@ module SimpleForm
59
60
  # we need the hidden field to be *outside* the label (otherwise it
60
61
  # generates invalid html - html5 only).
61
62
  def build_hidden_field_for_checkbox
62
- return "" unless include_hidden?
63
+ return "" if !include_hidden? || !unchecked_value
63
64
  options = { value: unchecked_value, id: nil, disabled: input_html_options[:disabled] }
64
- options[:name] = input_html_options[:name] if input_html_options.has_key?(:name)
65
+ options[:name] = input_html_options[:name] if input_html_options.key?(:name)
66
+ options[:form] = input_html_options[:form] if input_html_options.key?(:form)
65
67
 
66
68
  @builder.hidden_field(attribute_name, options)
67
69
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class CollectionCheckBoxesInput < CollectionRadioButtonsInput
@@ -10,7 +11,7 @@ module SimpleForm
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
@@ -45,7 +46,7 @@ module SimpleForm
45
46
 
46
47
  # Check if :include_blank must be included by default.
47
48
  def skip_include_blank?
48
- (options.keys & [:prompt, :include_blank, :default, :selected]).any? || multiple?
49
+ (options.keys & %i[prompt include_blank default selected]).any? || multiple?
49
50
  end
50
51
 
51
52
  def multiple?
@@ -89,7 +90,7 @@ module SimpleForm
89
90
  end
90
91
 
91
92
  def detect_collection_classes(some_collection = collection)
92
- some_collection.map { |e| e.class }.uniq
93
+ some_collection.map(&:class).uniq
93
94
  end
94
95
 
95
96
  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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
3
  module Inputs
3
4
  class RangeInput < NumericInput
@@ -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
@@ -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
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module SimpleForm
2
- VERSION = "3.4.0".freeze
3
+ VERSION = "4.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