simple_form 3.1.0 → 5.0.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.
- 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