simple_form 3.1.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +148 -0
- data/MIT-LICENSE +1 -1
- data/README.md +278 -68
- data/lib/generators/simple_form/install_generator.rb +1 -0
- data/lib/generators/simple_form/templates/README +3 -3
- data/lib/generators/simple_form/templates/_form.html.erb +2 -0
- data/lib/generators/simple_form/templates/_form.html.haml +2 -0
- data/lib/generators/simple_form/templates/_form.html.slim +1 -0
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +19 -9
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +367 -63
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +23 -8
- data/lib/simple_form/action_view_extensions/builder.rb +1 -0
- data/lib/simple_form/action_view_extensions/form_helper.rb +4 -1
- data/lib/simple_form/components/errors.rb +15 -2
- data/lib/simple_form/components/hints.rb +1 -0
- data/lib/simple_form/components/html5.rb +15 -4
- data/lib/simple_form/components/label_input.rb +2 -1
- data/lib/simple_form/components/labels.rb +12 -5
- data/lib/simple_form/components/maxlength.rb +8 -4
- data/lib/simple_form/components/min_max.rb +1 -0
- data/lib/simple_form/components/minlength.rb +38 -0
- data/lib/simple_form/components/pattern.rb +1 -0
- data/lib/simple_form/components/placeholders.rb +2 -1
- data/lib/simple_form/components/readonly.rb +1 -0
- data/lib/simple_form/components.rb +2 -0
- data/lib/simple_form/error_notification.rb +1 -0
- data/lib/simple_form/form_builder.rb +117 -35
- data/lib/simple_form/helpers/autofocus.rb +1 -0
- data/lib/simple_form/helpers/disabled.rb +1 -0
- data/lib/simple_form/helpers/readonly.rb +1 -0
- data/lib/simple_form/helpers/required.rb +1 -0
- data/lib/simple_form/helpers/validators.rb +2 -1
- data/lib/simple_form/helpers.rb +1 -0
- data/lib/simple_form/i18n_cache.rb +1 -0
- data/lib/simple_form/inputs/base.rb +36 -12
- data/lib/simple_form/inputs/block_input.rb +1 -0
- data/lib/simple_form/inputs/boolean_input.rb +14 -3
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +2 -1
- data/lib/simple_form/inputs/collection_input.rb +7 -5
- data/lib/simple_form/inputs/collection_radio_buttons_input.rb +3 -2
- data/lib/simple_form/inputs/collection_select_input.rb +1 -0
- data/lib/simple_form/inputs/color_input.rb +14 -0
- data/lib/simple_form/inputs/date_time_input.rb +13 -8
- data/lib/simple_form/inputs/file_input.rb +1 -0
- data/lib/simple_form/inputs/grouped_collection_select_input.rb +1 -0
- data/lib/simple_form/inputs/hidden_input.rb +1 -0
- data/lib/simple_form/inputs/numeric_input.rb +1 -0
- data/lib/simple_form/inputs/password_input.rb +2 -1
- data/lib/simple_form/inputs/priority_input.rb +1 -4
- data/lib/simple_form/inputs/range_input.rb +1 -0
- data/lib/simple_form/inputs/string_input.rb +3 -2
- data/lib/simple_form/inputs/text_input.rb +2 -1
- data/lib/simple_form/inputs.rb +2 -0
- data/lib/simple_form/map_type.rb +1 -0
- data/lib/simple_form/railtie.rb +1 -0
- data/lib/simple_form/tags.rb +7 -2
- data/lib/simple_form/version.rb +2 -1
- data/lib/simple_form/wrappers/builder.rb +1 -0
- data/lib/simple_form/wrappers/leaf.rb +2 -1
- data/lib/simple_form/wrappers/many.rb +1 -0
- data/lib/simple_form/wrappers/root.rb +2 -0
- data/lib/simple_form/wrappers/single.rb +2 -1
- data/lib/simple_form/wrappers.rb +1 -0
- data/lib/simple_form.rb +79 -14
- data/test/action_view_extensions/builder_test.rb +28 -9
- data/test/action_view_extensions/form_helper_test.rb +3 -2
- data/test/components/custom_components_test.rb +62 -0
- data/test/components/label_test.rb +33 -4
- data/test/form_builder/association_test.rb +33 -2
- data/test/form_builder/button_test.rb +1 -0
- data/test/form_builder/error_notification_test.rb +1 -0
- data/test/form_builder/error_test.rb +44 -9
- data/test/form_builder/general_test.rb +92 -20
- data/test/form_builder/hint_test.rb +6 -0
- data/test/form_builder/input_field_test.rb +76 -70
- data/test/form_builder/label_test.rb +27 -4
- data/test/form_builder/wrapper_test.rb +66 -14
- data/test/generators/simple_form_generator_test.rb +4 -3
- data/test/inputs/boolean_input_test.rb +35 -0
- data/test/inputs/collection_check_boxes_input_test.rb +38 -14
- data/test/inputs/collection_radio_buttons_input_test.rb +48 -24
- data/test/inputs/collection_select_input_test.rb +40 -39
- data/test/inputs/color_input_test.rb +10 -0
- data/test/inputs/datetime_input_test.rb +12 -8
- data/test/inputs/disabled_test.rb +14 -0
- data/test/inputs/discovery_test.rb +23 -0
- data/test/inputs/file_input_test.rb +1 -0
- data/test/inputs/general_test.rb +3 -2
- data/test/inputs/grouped_collection_select_input_test.rb +11 -10
- data/test/inputs/hidden_input_test.rb +1 -0
- data/test/inputs/numeric_input_test.rb +5 -1
- data/test/inputs/priority_input_test.rb +7 -6
- data/test/inputs/readonly_test.rb +1 -0
- data/test/inputs/required_test.rb +45 -0
- data/test/inputs/string_input_test.rb +18 -16
- data/test/inputs/text_input_test.rb +13 -0
- data/test/simple_form_test.rb +1 -0
- data/test/support/discovery_inputs.rb +8 -0
- data/test/support/misc_helpers.rb +44 -2
- data/test/support/mock_controller.rb +7 -1
- data/test/support/models.rb +105 -22
- data/test/test_helper.rb +14 -3
- metadata +42 -36
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module SimpleForm
|
2
3
|
module Components
|
3
4
|
module Errors
|
@@ -10,7 +11,15 @@ module SimpleForm
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def has_errors?
|
13
|
-
|
14
|
+
object_with_errors? || object.nil? && has_custom_error?
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_value?
|
18
|
+
object && object.respond_to?(attribute_name) && object.send(attribute_name).present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
!has_errors? && has_value?
|
14
23
|
end
|
15
24
|
|
16
25
|
protected
|
@@ -25,6 +34,10 @@ module SimpleForm
|
|
25
34
|
has_custom_error? ? options[:error] : full_errors.send(error_method)
|
26
35
|
end
|
27
36
|
|
37
|
+
def object_with_errors?
|
38
|
+
object && object.respond_to?(:errors) && errors.present?
|
39
|
+
end
|
40
|
+
|
28
41
|
def error_method
|
29
42
|
options[:error_method] || SimpleForm.error_method
|
30
43
|
end
|
@@ -38,7 +51,7 @@ module SimpleForm
|
|
38
51
|
end
|
39
52
|
|
40
53
|
def errors_on_attribute
|
41
|
-
object.errors[attribute_name]
|
54
|
+
object.errors[attribute_name] || []
|
42
55
|
end
|
43
56
|
|
44
57
|
def full_errors_on_attribute
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module SimpleForm
|
2
3
|
module Components
|
3
4
|
module HTML5
|
@@ -7,10 +8,12 @@ module SimpleForm
|
|
7
8
|
|
8
9
|
def html5(wrapper_options = nil)
|
9
10
|
@html5 = true
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
|
12
|
+
input_html_options[:required] = input_html_required_option
|
13
|
+
input_html_options[:'aria-required'] = input_html_aria_required_option
|
14
|
+
|
15
|
+
input_html_options[:'aria-invalid'] = has_errors? || nil
|
16
|
+
|
14
17
|
nil
|
15
18
|
end
|
16
19
|
|
@@ -18,6 +21,14 @@ module SimpleForm
|
|
18
21
|
@html5
|
19
22
|
end
|
20
23
|
|
24
|
+
def input_html_required_option
|
25
|
+
!options[:required].nil? ? required_field? : has_required?
|
26
|
+
end
|
27
|
+
|
28
|
+
def input_html_aria_required_option
|
29
|
+
!options[:required].nil? ? (required_field? || nil) : (has_required? || nil)
|
30
|
+
end
|
31
|
+
|
21
32
|
def has_required?
|
22
33
|
# We need to check browser_validations because
|
23
34
|
# some browsers are still checking required even
|
@@ -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
|
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(:"
|
10
|
-
%
|
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(:"
|
17
|
+
I18n.t(:"required.text", scope: i18n_scope, default: 'required')
|
17
18
|
end
|
18
19
|
|
19
20
|
def translate_required_mark
|
20
|
-
I18n.t(:"
|
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
|
|
@@ -42,7 +49,7 @@ module SimpleForm
|
|
42
49
|
|
43
50
|
def label_html_options
|
44
51
|
label_html_classes = SimpleForm.additional_classes_for(:label) {
|
45
|
-
[input_type, required_class, SimpleForm.label_class].compact
|
52
|
+
[input_type, required_class, disabled_class, SimpleForm.label_class].compact
|
46
53
|
}
|
47
54
|
|
48
55
|
label_options = html_options_for(:label, label_html_classes)
|
@@ -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.
|
@@ -15,10 +16,7 @@ module SimpleForm
|
|
15
16
|
maxlength
|
16
17
|
else
|
17
18
|
length_validator = find_length_validator
|
18
|
-
|
19
|
-
if length_validator && !has_tokenizer?(length_validator)
|
20
|
-
length_validator.options[:is] || length_validator.options[:maximum]
|
21
|
-
end
|
19
|
+
maximum_length_value_from(length_validator)
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -29,6 +27,12 @@ module SimpleForm
|
|
29
27
|
def has_tokenizer?(length_validator)
|
30
28
|
length_validator.options[:tokenizer]
|
31
29
|
end
|
30
|
+
|
31
|
+
def maximum_length_value_from(length_validator)
|
32
|
+
if length_validator
|
33
|
+
length_validator.options[:is] || length_validator.options[:maximum]
|
34
|
+
end
|
35
|
+
end
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module SimpleForm
|
3
|
+
module Components
|
4
|
+
# Needs to be enabled in order to do automatic lookups.
|
5
|
+
module Minlength
|
6
|
+
def minlength(wrapper_options = nil)
|
7
|
+
input_html_options[:minlength] ||= minimum_length_from_validation
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def minimum_length_from_validation
|
14
|
+
minlength = options[:minlength]
|
15
|
+
if minlength.is_a?(String) || minlength.is_a?(Integer)
|
16
|
+
minlength
|
17
|
+
else
|
18
|
+
length_validator = find_length_validator
|
19
|
+
minimum_length_value_from(length_validator)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_length_validator
|
24
|
+
find_validator(:length)
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_tokenizer?(length_validator)
|
28
|
+
length_validator.options[:tokenizer]
|
29
|
+
end
|
30
|
+
|
31
|
+
def minimum_length_value_from(length_validator)
|
32
|
+
if length_validator
|
33
|
+
length_validator.options[:is] || length_validator.options[:minimum]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
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.
|
@@ -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
|
# 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
|
@@ -15,6 +16,7 @@ module SimpleForm
|
|
15
16
|
autoload :Labels
|
16
17
|
autoload :MinMax
|
17
18
|
autoload :Maxlength
|
19
|
+
autoload :Minlength
|
18
20
|
autoload :Pattern
|
19
21
|
autoload :Placeholders
|
20
22
|
autoload :Readonly
|
@@ -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,24 +13,25 @@ module SimpleForm
|
|
12
13
|
'update' => 'edit'
|
13
14
|
}
|
14
15
|
|
15
|
-
ATTRIBUTE_COMPONENTS = [
|
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,
|
21
|
-
map_type :file,
|
22
|
-
map_type :string, :email, :search, :tel, :url, :uuid, to: SimpleForm::Inputs::StringInput
|
23
|
-
map_type :password,
|
24
|
-
map_type :integer, :decimal, :float,
|
25
|
-
map_type :range,
|
26
|
-
map_type :check_boxes,
|
27
|
-
map_type :radio_buttons,
|
28
|
-
map_type :select,
|
29
|
-
map_type :grouped_select,
|
30
|
-
map_type :date, :time, :datetime,
|
31
|
-
map_type :country, :time_zone,
|
32
|
-
map_type :boolean,
|
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
|
33
35
|
|
34
36
|
def self.discovery_cache
|
35
37
|
@discovery_cache ||= {}
|
@@ -37,6 +39,7 @@ module SimpleForm
|
|
37
39
|
|
38
40
|
def initialize(*) #:nodoc:
|
39
41
|
super
|
42
|
+
@object = convert_to_model(@object)
|
40
43
|
@defaults = options[:defaults]
|
41
44
|
@wrapper = SimpleForm.wrapper(options[:wrapper] || SimpleForm.default_wrapper)
|
42
45
|
end
|
@@ -47,6 +50,11 @@ module SimpleForm
|
|
47
50
|
# label + input + hint (when defined) + errors (when exists), and all can
|
48
51
|
# be configured inside a wrapper html.
|
49
52
|
#
|
53
|
+
# If a block is given, the contents of the block will replace the input
|
54
|
+
# field that would otherwise be generated automatically. The content will
|
55
|
+
# be given a label and wrapper div to make it consistent with the other
|
56
|
+
# elements in the form.
|
57
|
+
#
|
50
58
|
# == Examples
|
51
59
|
#
|
52
60
|
# # Imagine @user has error "can't be blank" on name
|
@@ -130,16 +138,39 @@ module SimpleForm
|
|
130
138
|
# <input class="string required" id="user_name" maxlength="100"
|
131
139
|
# name="user[name]" type="text" value="Carlos" />
|
132
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
|
+
#
|
133
164
|
def input_field(attribute_name, options = {})
|
134
165
|
components = (wrapper.components.map(&:namespace) & ATTRIBUTE_COMPONENTS)
|
135
166
|
|
136
167
|
options = options.dup
|
137
|
-
options[:input_html] = options.except(:as, :boolean_style, :collection, :label_method, :value_method, *components)
|
168
|
+
options[:input_html] = options.except(:as, :boolean_style, :collection, :disabled, :label_method, :value_method, :prompt, *components)
|
138
169
|
options = @defaults.deep_dup.deep_merge(options) if @defaults
|
139
170
|
|
140
171
|
input = find_input(attribute_name, options)
|
141
172
|
wrapper = find_wrapper(input.input_type, options)
|
142
|
-
components = components.
|
173
|
+
components = build_input_field_components(components.push(:input))
|
143
174
|
|
144
175
|
SimpleForm::Wrappers::Root.new(components, wrapper.options.merge(wrapper: false)).render input
|
145
176
|
end
|
@@ -206,8 +237,8 @@ module SimpleForm
|
|
206
237
|
options = args.extract_options!.dup
|
207
238
|
options[:class] = [SimpleForm.button_class, options[:class]].compact
|
208
239
|
args << options
|
209
|
-
if respond_to?("#{type}_button")
|
210
|
-
send("#{type}_button", *args, &block)
|
240
|
+
if respond_to?(:"#{type}_button")
|
241
|
+
send(:"#{type}_button", *args, &block)
|
211
242
|
else
|
212
243
|
send(type, *args, &block)
|
213
244
|
end
|
@@ -284,7 +315,7 @@ module SimpleForm
|
|
284
315
|
#
|
285
316
|
# f.label :name # Do I18n lookup
|
286
317
|
# f.label :name, "Name" # Same behavior as Rails, do not add required tag
|
287
|
-
# f.label :name, label: "Name"
|
318
|
+
# f.label :name, label: "Name" # Same as above, but adds required tag
|
288
319
|
#
|
289
320
|
# f.label :name, required: false
|
290
321
|
# f.label :name, id: "cool_label"
|
@@ -293,7 +324,7 @@ module SimpleForm
|
|
293
324
|
return super if args.first.is_a?(String) || block_given?
|
294
325
|
|
295
326
|
options = args.extract_options!.dup
|
296
|
-
options[:label_html] = options.except(:label, :required, :as)
|
327
|
+
options[:label_html] = options.except(:label, :label_text, :required, :as)
|
297
328
|
|
298
329
|
column = find_attribute_column(attribute_name)
|
299
330
|
input_type = default_input_type(attribute_name, column, options)
|
@@ -455,13 +486,17 @@ module SimpleForm
|
|
455
486
|
relation = reflection.klass.all
|
456
487
|
|
457
488
|
if reflection.respond_to?(:scope) && reflection.scope
|
458
|
-
|
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
|
459
494
|
else
|
460
495
|
order = reflection.options[:order]
|
461
496
|
conditions = reflection.options[:conditions]
|
462
497
|
conditions = object.instance_exec(&conditions) if conditions.respond_to?(:call)
|
463
498
|
|
464
|
-
relation = relation.where(conditions)
|
499
|
+
relation = relation.where(conditions) if relation.respond_to?(:where)
|
465
500
|
relation = relation.order(order) if relation.respond_to?(:order)
|
466
501
|
end
|
467
502
|
|
@@ -476,7 +511,7 @@ module SimpleForm
|
|
476
511
|
when :has_one
|
477
512
|
raise ArgumentError, ":has_one associations are not supported by f.association"
|
478
513
|
else
|
479
|
-
if options[:as] == :select
|
514
|
+
if options[:as] == :select || options[:as] == :grouped_select
|
480
515
|
html_options = options[:input_html] ||= {}
|
481
516
|
html_options[:multiple] = true unless html_options.key?(:multiple)
|
482
517
|
end
|
@@ -504,25 +539,25 @@ module SimpleForm
|
|
504
539
|
end
|
505
540
|
|
506
541
|
# Attempt to guess the better input type given the defined options. By
|
507
|
-
# default
|
542
|
+
# default always fallback to the user :as option, or to a :select when a
|
508
543
|
# collection is given.
|
509
544
|
def default_input_type(attribute_name, column, options)
|
510
545
|
return options[:as].to_sym if options[:as]
|
511
|
-
return :select if options[:collection]
|
512
546
|
custom_type = find_custom_type(attribute_name.to_s) and return custom_type
|
547
|
+
return :select if options[:collection]
|
513
548
|
|
514
549
|
input_type = column.try(:type)
|
515
550
|
case input_type
|
516
551
|
when :timestamp
|
517
552
|
:datetime
|
518
|
-
when :string, nil
|
553
|
+
when :string, :citext, nil
|
519
554
|
case attribute_name.to_s
|
520
|
-
when /password/ then :password
|
521
|
-
when /time_zone/ then :time_zone
|
522
|
-
when /country/ then :country
|
523
|
-
when /email/ then :email
|
524
|
-
when /phone/ then :tel
|
525
|
-
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
|
526
561
|
else
|
527
562
|
file_method?(attribute_name) ? :file : (input_type || :string)
|
528
563
|
end
|
@@ -537,13 +572,34 @@ module SimpleForm
|
|
537
572
|
}.try(:last) if SimpleForm.input_mappings
|
538
573
|
end
|
539
574
|
|
575
|
+
# Internal: Try to discover whether an attribute corresponds to a file or not.
|
576
|
+
#
|
577
|
+
# Most upload Gems add some kind of attributes to the ActiveRecord's model they are included in.
|
578
|
+
# This method tries to guess if an attribute belongs to some of these Gems by checking the presence
|
579
|
+
# of their methods using `#respond_to?`.
|
580
|
+
#
|
581
|
+
# Note: This does not support multiple file upload inputs, as this is very application-specific.
|
582
|
+
#
|
583
|
+
# The order here was choosen based on the popularity of Gems and for commodity - e.g. the method
|
584
|
+
# with the suffix `_url` is present in three Gems, so it's checked with priority:
|
585
|
+
#
|
586
|
+
# - `#{attribute_name}_attachment` - ActiveStorage >= `5.2` and Refile >= `0.2.0` <= `0.4.0`
|
587
|
+
# - `#{attribute_name}_url` - Shrine >= `0.9.0`, Refile >= `0.6.0` and CarrierWave >= `0.2.1`
|
588
|
+
# - `#{attribute_name}_attacher` - Refile >= `0.4.0` and Shrine >= `0.9.0`
|
589
|
+
# - `#{attribute_name}_file_name` - Paperclip ~> `2.0` (added for backwards compatibility)
|
590
|
+
#
|
591
|
+
# Returns a Boolean.
|
540
592
|
def file_method?(attribute_name)
|
541
|
-
|
542
|
-
|
593
|
+
@object.respond_to?("#{attribute_name}_attachment") ||
|
594
|
+
@object.respond_to?("#{attribute_name}_url") ||
|
595
|
+
@object.respond_to?("#{attribute_name}_attacher") ||
|
596
|
+
@object.respond_to?("#{attribute_name}_file_name")
|
543
597
|
end
|
544
598
|
|
545
599
|
def find_attribute_column(attribute_name)
|
546
|
-
if @object.respond_to?(:
|
600
|
+
if @object.respond_to?(:type_for_attribute) && @object.has_attribute?(attribute_name)
|
601
|
+
@object.type_for_attribute(attribute_name.to_s)
|
602
|
+
elsif @object.respond_to?(:column_for_attribute) && @object.has_attribute?(attribute_name)
|
547
603
|
@object.column_for_attribute(attribute_name)
|
548
604
|
end
|
549
605
|
end
|
@@ -632,5 +688,31 @@ module SimpleForm
|
|
632
688
|
|
633
689
|
nil
|
634
690
|
end
|
691
|
+
|
692
|
+
def build_input_field_components(components)
|
693
|
+
components.map do |component|
|
694
|
+
if component == :input
|
695
|
+
SimpleForm::Wrappers::Leaf.new(component, build_input_field_options)
|
696
|
+
else
|
697
|
+
SimpleForm::Wrappers::Leaf.new(component)
|
698
|
+
end
|
699
|
+
end
|
700
|
+
end
|
701
|
+
|
702
|
+
def build_input_field_options
|
703
|
+
input_field_options = {}
|
704
|
+
valid_class = SimpleForm.input_field_valid_class
|
705
|
+
error_class = SimpleForm.input_field_error_class
|
706
|
+
|
707
|
+
if error_class.present?
|
708
|
+
input_field_options[:error_class] = error_class
|
709
|
+
end
|
710
|
+
|
711
|
+
if valid_class.present?
|
712
|
+
input_field_options[:valid_class] = valid_class
|
713
|
+
end
|
714
|
+
|
715
|
+
input_field_options
|
716
|
+
end
|
635
717
|
end
|
636
718
|
end
|
@@ -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
|
28
|
+
return true unless validator.options.include?(:on)
|
28
29
|
|
29
30
|
case validator.options[:on]
|
30
31
|
when :save
|
data/lib/simple_form/helpers.rb
CHANGED