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

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