mini-sharp-mod 0.0.1

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 (70) hide show
  1. checksums.yaml +7 -0
  2. data/mini-sharp-mod.gemspec +12 -0
  3. data/simple_form-5.4.1/CHANGELOG.md +259 -0
  4. data/simple_form-5.4.1/MIT-LICENSE +21 -0
  5. data/simple_form-5.4.1/README.md +1334 -0
  6. data/simple_form-5.4.1/lib/generators/simple_form/USAGE +3 -0
  7. data/simple_form-5.4.1/lib/generators/simple_form/install_generator.rb +42 -0
  8. data/simple_form-5.4.1/lib/generators/simple_form/templates/README +10 -0
  9. data/simple_form-5.4.1/lib/generators/simple_form/templates/_form.html.erb +15 -0
  10. data/simple_form-5.4.1/lib/generators/simple_form/templates/_form.html.haml +12 -0
  11. data/simple_form-5.4.1/lib/generators/simple_form/templates/_form.html.slim +11 -0
  12. data/simple_form-5.4.1/lib/generators/simple_form/templates/config/initializers/simple_form.rb +176 -0
  13. data/simple_form-5.4.1/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +372 -0
  14. data/simple_form-5.4.1/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +122 -0
  15. data/simple_form-5.4.1/lib/generators/simple_form/templates/config/locales/simple_form.en.yml +31 -0
  16. data/simple_form-5.4.1/lib/simple_form/action_view_extensions/builder.rb +38 -0
  17. data/simple_form-5.4.1/lib/simple_form/action_view_extensions/form_helper.rb +72 -0
  18. data/simple_form-5.4.1/lib/simple_form/components/errors.rb +74 -0
  19. data/simple_form-5.4.1/lib/simple_form/components/hints.rb +24 -0
  20. data/simple_form-5.4.1/lib/simple_form/components/html5.rb +33 -0
  21. data/simple_form-5.4.1/lib/simple_form/components/label_input.rb +34 -0
  22. data/simple_form-5.4.1/lib/simple_form/components/labels.rb +88 -0
  23. data/simple_form-5.4.1/lib/simple_form/components/maxlength.rb +35 -0
  24. data/simple_form-5.4.1/lib/simple_form/components/min_max.rb +41 -0
  25. data/simple_form-5.4.1/lib/simple_form/components/minlength.rb +35 -0
  26. data/simple_form-5.4.1/lib/simple_form/components/pattern.rb +27 -0
  27. data/simple_form-5.4.1/lib/simple_form/components/placeholders.rb +17 -0
  28. data/simple_form-5.4.1/lib/simple_form/components/readonly.rb +23 -0
  29. data/simple_form-5.4.1/lib/simple_form/components.rb +24 -0
  30. data/simple_form-5.4.1/lib/simple_form/error_notification.rb +49 -0
  31. data/simple_form-5.4.1/lib/simple_form/form_builder.rb +723 -0
  32. data/simple_form-5.4.1/lib/simple_form/helpers/autofocus.rb +12 -0
  33. data/simple_form-5.4.1/lib/simple_form/helpers/disabled.rb +16 -0
  34. data/simple_form-5.4.1/lib/simple_form/helpers/readonly.rb +16 -0
  35. data/simple_form-5.4.1/lib/simple_form/helpers/required.rb +36 -0
  36. data/simple_form-5.4.1/lib/simple_form/helpers/validators.rb +66 -0
  37. data/simple_form-5.4.1/lib/simple_form/helpers.rb +13 -0
  38. data/simple_form-5.4.1/lib/simple_form/inputs/base.rb +232 -0
  39. data/simple_form-5.4.1/lib/simple_form/inputs/block_input.rb +15 -0
  40. data/simple_form-5.4.1/lib/simple_form/inputs/boolean_input.rb +108 -0
  41. data/simple_form-5.4.1/lib/simple_form/inputs/collection_check_boxes_input.rb +22 -0
  42. data/simple_form-5.4.1/lib/simple_form/inputs/collection_input.rb +122 -0
  43. data/simple_form-5.4.1/lib/simple_form/inputs/collection_radio_buttons_input.rb +59 -0
  44. data/simple_form-5.4.1/lib/simple_form/inputs/collection_select_input.rb +17 -0
  45. data/simple_form-5.4.1/lib/simple_form/inputs/color_input.rb +14 -0
  46. data/simple_form-5.4.1/lib/simple_form/inputs/date_time_input.rb +39 -0
  47. data/simple_form-5.4.1/lib/simple_form/inputs/file_input.rb +12 -0
  48. data/simple_form-5.4.1/lib/simple_form/inputs/grouped_collection_select_input.rb +54 -0
  49. data/simple_form-5.4.1/lib/simple_form/inputs/hidden_input.rb +20 -0
  50. data/simple_form-5.4.1/lib/simple_form/inputs/numeric_input.rb +20 -0
  51. data/simple_form-5.4.1/lib/simple_form/inputs/password_input.rb +14 -0
  52. data/simple_form-5.4.1/lib/simple_form/inputs/priority_input.rb +37 -0
  53. data/simple_form-5.4.1/lib/simple_form/inputs/range_input.rb +15 -0
  54. data/simple_form-5.4.1/lib/simple_form/inputs/rich_text_area_input.rb +14 -0
  55. data/simple_form-5.4.1/lib/simple_form/inputs/string_input.rb +25 -0
  56. data/simple_form-5.4.1/lib/simple_form/inputs/text_input.rb +14 -0
  57. data/simple_form-5.4.1/lib/simple_form/inputs/weekday_input.rb +14 -0
  58. data/simple_form-5.4.1/lib/simple_form/inputs.rb +27 -0
  59. data/simple_form-5.4.1/lib/simple_form/map_type.rb +17 -0
  60. data/simple_form-5.4.1/lib/simple_form/railtie.rb +19 -0
  61. data/simple_form-5.4.1/lib/simple_form/tags.rb +73 -0
  62. data/simple_form-5.4.1/lib/simple_form/version.rb +4 -0
  63. data/simple_form-5.4.1/lib/simple_form/wrappers/builder.rb +80 -0
  64. data/simple_form-5.4.1/lib/simple_form/wrappers/leaf.rb +29 -0
  65. data/simple_form-5.4.1/lib/simple_form/wrappers/many.rb +74 -0
  66. data/simple_form-5.4.1/lib/simple_form/wrappers/root.rb +43 -0
  67. data/simple_form-5.4.1/lib/simple_form/wrappers/single.rb +27 -0
  68. data/simple_form-5.4.1/lib/simple_form/wrappers.rb +10 -0
  69. data/simple_form-5.4.1/lib/simple_form.rb +340 -0
  70. metadata +109 -0
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Helpers
4
+ module Autofocus
5
+ private
6
+
7
+ def has_autofocus?
8
+ options[:autofocus] == true
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Helpers
4
+ module Disabled
5
+ private
6
+
7
+ def has_disabled?
8
+ options[:disabled] == true
9
+ end
10
+
11
+ def disabled_class
12
+ :disabled if has_disabled?
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Helpers
4
+ module Readonly
5
+ private
6
+
7
+ def readonly_class
8
+ :readonly if has_readonly?
9
+ end
10
+
11
+ def has_readonly?
12
+ options[:readonly] == true
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Helpers
4
+ module Required
5
+ private
6
+
7
+ def required_field?
8
+ @required
9
+ end
10
+
11
+ def calculate_required
12
+ if !options[:required].nil?
13
+ options[:required]
14
+ elsif has_validators?
15
+ required_by_validators?
16
+ else
17
+ required_by_default?
18
+ end
19
+ end
20
+
21
+ def required_by_validators?
22
+ (attribute_validators + reflection_validators).any? { |v| v.kind == :presence && valid_validator?(v) }
23
+ end
24
+
25
+ def required_by_default?
26
+ SimpleForm.required_by_default
27
+ end
28
+
29
+ # Do not use has_required? because we want to add the class
30
+ # regardless of the required option.
31
+ def required_class
32
+ required_field? ? :required : :optional
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Helpers
4
+ module Validators
5
+ def has_validators?
6
+ @has_validators ||= attribute_name && object.class.respond_to?(:validators_on)
7
+ end
8
+
9
+ private
10
+
11
+ def attribute_validators
12
+ object.class.validators_on(attribute_name)
13
+ end
14
+
15
+ def reflection_validators
16
+ reflection ? object.class.validators_on(reflection.name) : []
17
+ end
18
+
19
+ def valid_validator?(validator)
20
+ !conditional_validators?(validator) && action_validator_match?(validator)
21
+ end
22
+
23
+ def conditional_validators?(validator)
24
+ validator.options.include?(:if) || validator.options.include?(:unless)
25
+ end
26
+
27
+ def action_validator_match?(validator)
28
+ return true unless validator.options.include?(:on)
29
+
30
+ case validator.options[:on]
31
+ when :save
32
+ true
33
+ when :create
34
+ !object.persisted?
35
+ when :update
36
+ object.persisted?
37
+ end
38
+ end
39
+
40
+ def find_validator(kind)
41
+ attribute_validators.find { |v| v.kind == kind } if has_validators?
42
+ end
43
+
44
+ # Implements `ActiveModel::Validations::ResolveValue`, introduced by Rails 7.1.
45
+ # https://github.com/rails/rails/blob/v7.1.0/activemodel/lib/active_model/validations/resolve_value.rb
46
+ def resolve_validator_value(value)
47
+ case value
48
+ when Proc
49
+ if value.arity == 0
50
+ value.call
51
+ else
52
+ value.call(object)
53
+ end
54
+ when Symbol
55
+ object.send(value)
56
+ else
57
+ if value.respond_to?(:call)
58
+ value.call(object)
59
+ else
60
+ value
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ # Helpers are made of several helpers that cannot be turned on automatically.
4
+ # For instance, disabled cannot be turned on automatically, it requires the
5
+ # user to explicitly pass the option disabled: true so it may work.
6
+ module Helpers
7
+ autoload :Autofocus, 'simple_form/helpers/autofocus'
8
+ autoload :Disabled, 'simple_form/helpers/disabled'
9
+ autoload :Readonly, 'simple_form/helpers/readonly'
10
+ autoload :Required, 'simple_form/helpers/required'
11
+ autoload :Validators, 'simple_form/helpers/validators'
12
+ end
13
+ end
@@ -0,0 +1,232 @@
1
+ # frozen_string_literal: true
2
+ require 'active_support/core_ext/string/output_safety'
3
+ require 'action_view/helpers'
4
+
5
+ module SimpleForm
6
+ module Inputs
7
+ class Base
8
+ include ERB::Util
9
+ include ActionView::Helpers::TranslationHelper
10
+
11
+ include SimpleForm::Helpers::Autofocus
12
+ include SimpleForm::Helpers::Disabled
13
+ include SimpleForm::Helpers::Readonly
14
+ include SimpleForm::Helpers::Required
15
+ include SimpleForm::Helpers::Validators
16
+
17
+ include SimpleForm::Components::Errors
18
+ include SimpleForm::Components::Hints
19
+ include SimpleForm::Components::HTML5
20
+ include SimpleForm::Components::LabelInput
21
+ include SimpleForm::Components::Maxlength
22
+ include SimpleForm::Components::Minlength
23
+ include SimpleForm::Components::MinMax
24
+ include SimpleForm::Components::Pattern
25
+ include SimpleForm::Components::Placeholders
26
+ include SimpleForm::Components::Readonly
27
+
28
+ attr_reader :attribute_name, :column, :input_type, :reflection,
29
+ :options, :input_html_options, :input_html_classes, :html_classes
30
+
31
+ delegate :template, :object, :object_name, :lookup_model_names, :lookup_action, to: :@builder
32
+
33
+ class_attribute :default_options
34
+ self.default_options = {}
35
+
36
+ def self.enable(*keys)
37
+ options = self.default_options.dup
38
+ keys.each { |key| options.delete(key) }
39
+ self.default_options = options
40
+ end
41
+
42
+ def self.disable(*keys)
43
+ options = self.default_options.dup
44
+ keys.each { |key| options[key] = false }
45
+ self.default_options = options
46
+ end
47
+
48
+ # Always enabled.
49
+ enable :hint
50
+
51
+ # Usually disabled, needs to be enabled explicitly passing true as option.
52
+ disable :maxlength, :minlength, :placeholder, :pattern, :min_max
53
+
54
+ def initialize(builder, attribute_name, column, input_type, options = {})
55
+ super
56
+
57
+ options = options.dup
58
+ @builder = builder
59
+ @attribute_name = attribute_name
60
+ @column = column
61
+ @input_type = input_type
62
+ @reflection = options.delete(:reflection)
63
+ @options = options.reverse_merge!(self.class.default_options)
64
+ @required = calculate_required
65
+
66
+ # Notice that html_options_for receives a reference to input_html_classes.
67
+ # This means that classes added dynamically to input_html_classes will
68
+ # still propagate to input_html_options.
69
+ @html_classes = SimpleForm.additional_classes_for(:input) { additional_classes }
70
+
71
+ @input_html_classes = @html_classes.dup
72
+
73
+ input_html_classes = self.input_html_classes
74
+
75
+ if SimpleForm.input_class && input_html_classes.any?
76
+ input_html_classes << SimpleForm.input_class
77
+ end
78
+
79
+ @input_html_options = html_options_for(:input, input_html_classes).tap do |o|
80
+ o[:readonly] = true if has_readonly?
81
+ o[:disabled] = true if has_disabled?
82
+ o[:autofocus] = true if has_autofocus?
83
+ end
84
+ end
85
+
86
+ def input(wrapper_options = nil)
87
+ raise NotImplementedError
88
+ end
89
+
90
+ def input_options
91
+ options
92
+ end
93
+
94
+ def additional_classes
95
+ @additional_classes ||= [input_type, required_class, readonly_class, disabled_class].compact
96
+ end
97
+
98
+ def input_class
99
+ "#{lookup_model_names.join('_')}_#{reflection_or_attribute_name}"
100
+ end
101
+
102
+ private
103
+
104
+ def limit
105
+ if column
106
+ decimal_or_float? ? decimal_limit : column_limit
107
+ end
108
+ end
109
+
110
+ def column_limit
111
+ column.limit
112
+ end
113
+
114
+ # Add one for decimal point
115
+ def decimal_limit
116
+ column_limit && (column_limit + 1)
117
+ end
118
+
119
+ def decimal_or_float?
120
+ column.type == :float || column.type == :decimal
121
+ end
122
+
123
+ def nested_boolean_style?
124
+ options.fetch(:boolean_style, SimpleForm.boolean_style) == :nested
125
+ end
126
+
127
+ # Find reflection name when available, otherwise use attribute
128
+ def reflection_or_attribute_name
129
+ @reflection_or_attribute_name ||= reflection ? reflection.name : attribute_name
130
+ end
131
+
132
+ # Retrieve options for the given namespace from the options hash
133
+ def html_options_for(namespace, css_classes)
134
+ html_options = options[:"#{namespace}_html"]
135
+ html_options = html_options ? html_options.dup : {}
136
+ css_classes << html_options[:class] if html_options.key?(:class)
137
+ html_options[:class] = css_classes unless css_classes.empty?
138
+ html_options
139
+ end
140
+
141
+ # Lookup translations for the given namespace using I18n, based on object name,
142
+ # actual action and attribute name. Lookup priority as follows:
143
+ #
144
+ # simple_form.{namespace}.{model}.{action}.{attribute}
145
+ # simple_form.{namespace}.{model}.{attribute}
146
+ # simple_form.{namespace}.defaults.{attribute}
147
+ #
148
+ # Namespace is used for :labels and :hints.
149
+ #
150
+ # Model is the actual object name, for a @user object you'll have :user.
151
+ # Action is the action being rendered, usually :new or :edit.
152
+ # And attribute is the attribute itself, :name for example.
153
+ #
154
+ # The lookup for nested attributes is also done in a nested format using
155
+ # both model and nested object names, such as follow:
156
+ #
157
+ # simple_form.{namespace}.{model}.{nested}.{action}.{attribute}
158
+ # simple_form.{namespace}.{model}.{nested}.{attribute}
159
+ # simple_form.{namespace}.{nested}.{action}.{attribute}
160
+ # simple_form.{namespace}.{nested}.{attribute}
161
+ # simple_form.{namespace}.defaults.{attribute}
162
+ #
163
+ # Example:
164
+ #
165
+ # simple_form:
166
+ # labels:
167
+ # user:
168
+ # new:
169
+ # email: 'E-mail para efetuar o sign in.'
170
+ # edit:
171
+ # email: 'E-mail.'
172
+ #
173
+ # Take a look at our locale example file.
174
+ def translate_from_namespace(namespace, default = '')
175
+ model_names = lookup_model_names.dup
176
+ lookups = []
177
+
178
+ while !model_names.empty?
179
+ joined_model_names = model_names.join(".")
180
+ model_names.shift
181
+
182
+ lookups << :"#{joined_model_names}.#{lookup_action}.#{reflection_or_attribute_name}"
183
+ lookups << :"#{joined_model_names}.#{reflection_or_attribute_name}"
184
+ end
185
+ lookups << :"defaults.#{lookup_action}.#{reflection_or_attribute_name}"
186
+ lookups << :"defaults.#{reflection_or_attribute_name}"
187
+ lookups << default
188
+
189
+ I18n.t(lookups.shift, scope: :"#{i18n_scope}.#{namespace}", default: lookups).presence
190
+ end
191
+
192
+ def merge_wrapper_options(options, wrapper_options)
193
+ if wrapper_options
194
+ wrapper_options = set_input_classes(wrapper_options)
195
+
196
+ wrapper_options.merge(options) do |key, oldval, newval|
197
+ case key.to_s
198
+ when "class"
199
+ Array(oldval) + Array(newval)
200
+ when "data", "aria"
201
+ oldval.merge(newval)
202
+ else
203
+ newval
204
+ end
205
+ end
206
+ else
207
+ options
208
+ end
209
+ end
210
+
211
+ def set_input_classes(wrapper_options)
212
+ wrapper_options = wrapper_options.dup
213
+ error_class = wrapper_options.delete(:error_class)
214
+ valid_class = wrapper_options.delete(:valid_class)
215
+
216
+ if error_class.present? && has_errors?
217
+ wrapper_options[:class] = "#{wrapper_options[:class]} #{error_class}"
218
+ end
219
+
220
+ if valid_class.present? && valid?
221
+ wrapper_options[:class] = "#{wrapper_options[:class]} #{valid_class}"
222
+ end
223
+
224
+ wrapper_options
225
+ end
226
+
227
+ def i18n_scope
228
+ SimpleForm.i18n_scope
229
+ end
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Inputs
4
+ class BlockInput < Base
5
+ def initialize(*args, &block)
6
+ super
7
+ @block = block
8
+ end
9
+
10
+ def input(wrapper_options = nil)
11
+ template.capture(&@block)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Inputs
4
+ class BooleanInput < Base
5
+ def input(wrapper_options = nil)
6
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
7
+
8
+ if nested_boolean_style?
9
+ build_hidden_field_for_checkbox +
10
+ template.label_tag(nil, class: boolean_label_class) {
11
+ build_check_box_without_hidden_field(merged_input_options) +
12
+ inline_label
13
+ }
14
+ else
15
+ if include_hidden?
16
+ build_check_box(unchecked_value, merged_input_options)
17
+ else
18
+ build_check_box_without_hidden_field(merged_input_options)
19
+ end
20
+ end
21
+ end
22
+
23
+ def label_input(wrapper_options = nil)
24
+ if options[:label] == false || inline_label?
25
+ input(wrapper_options)
26
+ elsif nested_boolean_style?
27
+ html_options = label_html_options.dup
28
+ html_options[:class] ||= []
29
+ html_options[:class].push(boolean_label_class) if boolean_label_class
30
+
31
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
32
+
33
+ build_hidden_field_for_checkbox +
34
+ @builder.label(label_target, html_options) {
35
+ build_check_box_without_hidden_field(merged_input_options) + label_text
36
+ }
37
+ else
38
+ input(wrapper_options) + label(wrapper_options)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def boolean_label_class
45
+ options[:boolean_label_class] || SimpleForm.boolean_label_class
46
+ end
47
+
48
+ # Build a checkbox tag using default unchecked value. This allows us to
49
+ # reuse the method for nested boolean style, but with no unchecked value,
50
+ # which won't generate the hidden checkbox. This is the default functionality
51
+ # in Rails > 3.2.1, and is backported in SimpleForm AV helpers.
52
+ def build_check_box(unchecked_value, options)
53
+ @builder.check_box(attribute_name, options, checked_value, unchecked_value)
54
+ end
55
+
56
+ # Build a checkbox without generating the hidden field. See
57
+ # #build_hidden_field_for_checkbox for more info.
58
+ def build_check_box_without_hidden_field(options)
59
+ build_check_box(nil, options)
60
+ end
61
+
62
+ # Create a hidden field for the current checkbox, so we can simulate Rails
63
+ # functionality with hidden + checkbox, but under a nested context, where
64
+ # we need the hidden field to be *outside* the label (otherwise it
65
+ # generates invalid html - html5 only).
66
+ def build_hidden_field_for_checkbox
67
+ return "".html_safe if !include_hidden? || !unchecked_value
68
+ options = { value: unchecked_value, id: nil, disabled: input_html_options[:disabled] }
69
+ options[:name] = input_html_options[:name] if input_html_options.key?(:name)
70
+ options[:form] = input_html_options[:form] if input_html_options.key?(:form)
71
+
72
+ @builder.hidden_field(attribute_name, options)
73
+ end
74
+
75
+ def inline_label?
76
+ nested_boolean_style? && options[:inline_label]
77
+ end
78
+
79
+ def inline_label
80
+ inline_option = options[:inline_label]
81
+
82
+ if inline_option
83
+ label = inline_option == true ? label_text : html_escape(inline_option)
84
+ " #{label}".html_safe
85
+ end
86
+ end
87
+
88
+ # Booleans are not required by default because in most of the cases
89
+ # it makes no sense marking them as required. The only exception is
90
+ # Terms of Use usually presented at most sites sign up screen.
91
+ def required_by_default?
92
+ false
93
+ end
94
+
95
+ def include_hidden?
96
+ options.fetch(:include_hidden, true)
97
+ end
98
+
99
+ def checked_value
100
+ options.fetch(:checked_value, '1')
101
+ end
102
+
103
+ def unchecked_value
104
+ options.fetch(:unchecked_value, '0')
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Inputs
4
+ class CollectionCheckBoxesInput < CollectionRadioButtonsInput
5
+ protected
6
+
7
+ # Checkbox components do not use the required html tag.
8
+ # More info: https://github.com/heartcombo/simple_form/issues/340#issuecomment-2871956
9
+ def has_required?
10
+ false
11
+ end
12
+
13
+ def build_nested_boolean_style_item_tag(collection_builder)
14
+ collection_builder.check_box + collection_builder.text.to_s
15
+ end
16
+
17
+ def item_wrapper_class
18
+ "checkbox"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+ module SimpleForm
3
+ module Inputs
4
+ class CollectionInput < Base
5
+ BASIC_OBJECT_CLASSES = [String, Integer, Float, NilClass, Symbol, TrueClass, FalseClass]
6
+ BASIC_OBJECT_CLASSES.push(Fixnum, Bignum) unless 1.class == Integer
7
+
8
+ # Default boolean collection for use with selects/radios when no
9
+ # collection is given. Always fallback to this boolean collection.
10
+ # Texts can be translated using i18n in "simple_form.yes" and
11
+ # "simple_form.no" keys. See the example locale file.
12
+ def self.boolean_collection
13
+ [ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
14
+ [I18n.t(:"simple_form.no", default: 'No'), false] ]
15
+ end
16
+
17
+ def input(wrapper_options = nil)
18
+ raise NotImplementedError,
19
+ "input should be implemented by classes inheriting from CollectionInput"
20
+ end
21
+
22
+ def input_options
23
+ options = super
24
+
25
+ options[:include_blank] = true unless skip_include_blank?
26
+ translate_option options, :prompt
27
+ translate_option options, :include_blank
28
+
29
+ options
30
+ end
31
+
32
+ private
33
+
34
+ def collection
35
+ @collection ||= begin
36
+ collection = options.delete(:collection) || self.class.boolean_collection
37
+ collection.respond_to?(:call) ? collection.call : collection.to_a
38
+ end
39
+ end
40
+
41
+ def has_required?
42
+ super && (input_options[:include_blank] || input_options[:prompt].present? || multiple?)
43
+ end
44
+
45
+ # Check if :include_blank must be included by default.
46
+ def skip_include_blank?
47
+ (options.keys & %i[prompt include_blank default selected]).any? || multiple?
48
+ end
49
+
50
+ def multiple?
51
+ !!options[:input_html].try(:[], :multiple)
52
+ end
53
+
54
+ # Detect the right method to find the label and value for a collection.
55
+ # If no label or value method are defined, will attempt to find them based
56
+ # on default label and value methods that can be configured through
57
+ # SimpleForm.collection_label_methods and
58
+ # SimpleForm.collection_value_methods.
59
+ def detect_collection_methods
60
+ label, value = options.delete(:label_method), options.delete(:value_method)
61
+
62
+ unless label && value
63
+ common_method_for = detect_common_display_methods
64
+ label ||= common_method_for[:label]
65
+ value ||= common_method_for[:value]
66
+ end
67
+
68
+ [label, value]
69
+ end
70
+
71
+ def detect_common_display_methods(collection_classes = detect_collection_classes)
72
+ collection_translated = translate_collection if collection_classes == [Symbol]
73
+
74
+ if collection_translated || collection_classes.include?(Array)
75
+ { label: :first, value: :second }
76
+ elsif collection_includes_basic_objects?(collection_classes)
77
+ { label: :to_s, value: :to_s }
78
+ else
79
+ detect_method_from_class(collection_classes)
80
+ end
81
+ end
82
+
83
+ def detect_method_from_class(collection_classes)
84
+ sample = collection.first || collection.last
85
+
86
+ { label: SimpleForm.collection_label_methods.find { |m| sample.respond_to?(m) },
87
+ value: SimpleForm.collection_value_methods.find { |m| sample.respond_to?(m) } }
88
+ end
89
+
90
+ def detect_collection_classes(some_collection = collection)
91
+ some_collection.map(&:class).uniq
92
+ end
93
+
94
+ def collection_includes_basic_objects?(collection_classes)
95
+ (collection_classes & BASIC_OBJECT_CLASSES).any?
96
+ end
97
+
98
+ def translate_collection
99
+ if translated_collection = translate_from_namespace(:options)
100
+ @collection = collection.map do |key|
101
+ html_key = "#{key}_html".to_sym
102
+
103
+ if translated_collection[html_key]
104
+ [translated_collection[html_key].html_safe || key, key.to_s]
105
+ else
106
+ [translated_collection[key] || key, key.to_s]
107
+ end
108
+ end
109
+ true
110
+ end
111
+ end
112
+
113
+ def translate_option(options, key)
114
+ if options[key] == :translate
115
+ namespace = key.to_s.pluralize
116
+
117
+ options[key] = translate_from_namespace(namespace, true)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end