simple_form 4.1.0 → 5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -9
- data/MIT-LICENSE +2 -1
- data/README.md +47 -51
- data/lib/generators/simple_form/templates/README +2 -3
- data/lib/generators/simple_form/templates/config/initializers/simple_form.rb +1 -4
- data/lib/generators/simple_form/templates/config/initializers/simple_form_bootstrap.rb +26 -25
- data/lib/generators/simple_form/templates/config/initializers/simple_form_foundation.rb +1 -1
- data/lib/simple_form.rb +22 -5
- data/lib/simple_form/components/labels.rb +3 -5
- data/lib/simple_form/components/maxlength.rb +0 -4
- data/lib/simple_form/components/minlength.rb +0 -4
- data/lib/simple_form/form_builder.rb +23 -3
- data/lib/simple_form/inputs.rb +1 -0
- data/lib/simple_form/inputs/base.rb +0 -3
- data/lib/simple_form/inputs/collection_check_boxes_input.rb +1 -1
- data/lib/simple_form/inputs/collection_input.rb +3 -5
- data/lib/simple_form/inputs/priority_input.rb +0 -4
- data/lib/simple_form/inputs/rich_text_area_input.rb +12 -0
- data/lib/simple_form/tags.rb +6 -2
- data/lib/simple_form/version.rb +1 -1
- data/lib/simple_form/wrappers/root.rb +8 -3
- data/test/action_view_extensions/builder_test.rb +22 -4
- data/test/components/label_test.rb +0 -4
- data/test/form_builder/association_test.rb +6 -0
- data/test/form_builder/general_test.rb +17 -19
- data/test/form_builder/label_test.rb +1 -1
- data/test/form_builder/wrapper_test.rb +8 -1
- data/test/inputs/collection_check_boxes_input_test.rb +8 -4
- data/test/inputs/collection_radio_buttons_input_test.rb +8 -4
- data/test/inputs/collection_select_input_test.rb +6 -4
- data/test/inputs/priority_input_test.rb +4 -4
- data/test/inputs/rich_text_area_input_test.rb +15 -0
- data/test/support/misc_helpers.rb +2 -2
- data/test/support/models.rb +28 -2
- data/test/test_helper.rb +7 -4
- metadata +16 -15
- data/lib/simple_form/i18n_cache.rb +0 -23
@@ -2,7 +2,7 @@
|
|
2
2
|
#
|
3
3
|
# Uncomment this and change the path if necessary to include your own
|
4
4
|
# components.
|
5
|
-
# See https://github.com/
|
5
|
+
# See https://github.com/heartcombo/simple_form#custom-components to know
|
6
6
|
# more about custom components.
|
7
7
|
# Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
|
8
8
|
#
|
data/lib/simple_form.rb
CHANGED
@@ -35,7 +35,18 @@ to
|
|
35
35
|
|
36
36
|
def %{name}(wrapper_options)
|
37
37
|
|
38
|
-
See https://github.com/
|
38
|
+
See https://github.com/heartcombo/simple_form/pull/997 for more information.
|
39
|
+
WARN
|
40
|
+
|
41
|
+
FILE_METHODS_DEPRECATION_WARN = <<-WARN
|
42
|
+
[SIMPLE_FORM] SimpleForm.file_methods is deprecated and has no effect.
|
43
|
+
|
44
|
+
Since version 5, Simple Form now supports automatically discover of file inputs for the following Gems: activestorage, carrierwave, paperclip, refile and shrine.
|
45
|
+
If you are using a custom method that is not from one of the supported Gems, please change your forms to pass the input type explicitly:
|
46
|
+
|
47
|
+
<%= form.input :avatar, as: :file %>
|
48
|
+
|
49
|
+
See http://blog.plataformatec.com.br/2019/09/incorrect-access-control-in-simple-form-cve-2019-16676 for more information.
|
39
50
|
WARN
|
40
51
|
|
41
52
|
@@configured = false
|
@@ -120,10 +131,6 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
120
131
|
mattr_accessor :browser_validations
|
121
132
|
@@browser_validations = true
|
122
133
|
|
123
|
-
# Collection of methods to detect if a file type was given.
|
124
|
-
mattr_accessor :file_methods
|
125
|
-
@@file_methods = %i[mounted_as file? public_filename attached?]
|
126
|
-
|
127
134
|
# Custom mappings for input types. This should be a hash containing a regexp
|
128
135
|
# to match as key, and the input type that will be used when the field name
|
129
136
|
# matches the regexp as value, such as { /count/ => :integer }.
|
@@ -265,6 +272,16 @@ See https://github.com/plataformatec/simple_form/pull/997 for more information.
|
|
265
272
|
@@form_class = value
|
266
273
|
end
|
267
274
|
|
275
|
+
def self.file_methods=(file_methods)
|
276
|
+
ActiveSupport::Deprecation.warn(FILE_METHODS_DEPRECATION_WARN, caller)
|
277
|
+
@@file_methods = file_methods
|
278
|
+
end
|
279
|
+
|
280
|
+
def self.file_methods
|
281
|
+
ActiveSupport::Deprecation.warn(FILE_METHODS_DEPRECATION_WARN, caller)
|
282
|
+
@@file_methods
|
283
|
+
end
|
284
|
+
|
268
285
|
# Default way to setup Simple Form. Run rails generate simple_form:install
|
269
286
|
# to create a fresh initializer with all configuration values.
|
270
287
|
def self.setup
|
@@ -6,11 +6,9 @@ module SimpleForm
|
|
6
6
|
|
7
7
|
module ClassMethods #:nodoc:
|
8
8
|
def translate_required_html
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
)
|
13
|
-
end
|
9
|
+
I18n.t(:"required.html", scope: i18n_scope, default:
|
10
|
+
%(<abbr title="#{translate_required_text}">#{translate_required_mark}</abbr>)
|
11
|
+
)
|
14
12
|
end
|
15
13
|
|
16
14
|
def translate_required_text
|
@@ -24,10 +24,6 @@ module SimpleForm
|
|
24
24
|
find_validator(:length)
|
25
25
|
end
|
26
26
|
|
27
|
-
def has_tokenizer?(length_validator)
|
28
|
-
length_validator.options[:tokenizer]
|
29
|
-
end
|
30
|
-
|
31
27
|
def maximum_length_value_from(length_validator)
|
32
28
|
if length_validator
|
33
29
|
length_validator.options[:is] || length_validator.options[:maximum]
|
@@ -24,10 +24,6 @@ module SimpleForm
|
|
24
24
|
find_validator(:length)
|
25
25
|
end
|
26
26
|
|
27
|
-
def has_tokenizer?(length_validator)
|
28
|
-
length_validator.options[:tokenizer]
|
29
|
-
end
|
30
|
-
|
31
27
|
def minimum_length_value_from(length_validator)
|
32
28
|
if length_validator
|
33
29
|
length_validator.options[:is] || length_validator.options[:minimum]
|
@@ -26,6 +26,7 @@ module SimpleForm
|
|
26
26
|
map_type :range, to: SimpleForm::Inputs::RangeInput
|
27
27
|
map_type :check_boxes, to: SimpleForm::Inputs::CollectionCheckBoxesInput
|
28
28
|
map_type :radio_buttons, to: SimpleForm::Inputs::CollectionRadioButtonsInput
|
29
|
+
map_type :rich_text_area, to: SimpleForm::Inputs::RichTextAreaInput
|
29
30
|
map_type :select, to: SimpleForm::Inputs::CollectionSelectInput
|
30
31
|
map_type :grouped_select, to: SimpleForm::Inputs::GroupedCollectionSelectInput
|
31
32
|
map_type :date, :time, :datetime, to: SimpleForm::Inputs::DateTimeInput
|
@@ -511,7 +512,7 @@ module SimpleForm
|
|
511
512
|
when :has_one
|
512
513
|
raise ArgumentError, ":has_one associations are not supported by f.association"
|
513
514
|
else
|
514
|
-
if options[:as] == :select
|
515
|
+
if options[:as] == :select || options[:as] == :grouped_select
|
515
516
|
html_options = options[:input_html] ||= {}
|
516
517
|
html_options[:multiple] = true unless html_options.key?(:multiple)
|
517
518
|
end
|
@@ -572,9 +573,28 @@ module SimpleForm
|
|
572
573
|
}.try(:last) if SimpleForm.input_mappings
|
573
574
|
end
|
574
575
|
|
576
|
+
# Internal: Try to discover whether an attribute corresponds to a file or not.
|
577
|
+
#
|
578
|
+
# Most upload Gems add some kind of attributes to the ActiveRecord's model they are included in.
|
579
|
+
# This method tries to guess if an attribute belongs to some of these Gems by checking the presence
|
580
|
+
# of their methods using `#respond_to?`.
|
581
|
+
#
|
582
|
+
# Note: This does not support multiple file upload inputs, as this is very application-specific.
|
583
|
+
#
|
584
|
+
# The order here was chosen based on the popularity of Gems:
|
585
|
+
#
|
586
|
+
# - `#{attribute_name}_attachment` - ActiveStorage >= `5.2` and Refile >= `0.2.0` <= `0.4.0`
|
587
|
+
# - `remote_#{attribute_name}_url` - Refile >= `0.3.0` and CarrierWave >= `0.2.2`
|
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.
|
575
592
|
def file_method?(attribute_name)
|
576
|
-
|
577
|
-
|
593
|
+
@object.respond_to?("#{attribute_name}_attachment") ||
|
594
|
+
@object.respond_to?("#{attribute_name}_attachments") ||
|
595
|
+
@object.respond_to?("remote_#{attribute_name}_url") ||
|
596
|
+
@object.respond_to?("#{attribute_name}_attacher") ||
|
597
|
+
@object.respond_to?("#{attribute_name}_file_name")
|
578
598
|
end
|
579
599
|
|
580
600
|
def find_attribute_column(attribute_name)
|
data/lib/simple_form/inputs.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'simple_form/i18n_cache'
|
3
2
|
require 'active_support/core_ext/string/output_safety'
|
4
3
|
require 'action_view/helpers'
|
5
4
|
|
@@ -9,8 +8,6 @@ module SimpleForm
|
|
9
8
|
include ERB::Util
|
10
9
|
include ActionView::Helpers::TranslationHelper
|
11
10
|
|
12
|
-
extend I18nCache
|
13
|
-
|
14
11
|
include SimpleForm::Helpers::Autofocus
|
15
12
|
include SimpleForm::Helpers::Disabled
|
16
13
|
include SimpleForm::Helpers::Readonly
|
@@ -5,7 +5,7 @@ module SimpleForm
|
|
5
5
|
protected
|
6
6
|
|
7
7
|
# Checkbox components do not use the required html tag.
|
8
|
-
# More info: https://github.com/
|
8
|
+
# More info: https://github.com/heartcombo/simple_form/issues/340#issuecomment-2871956
|
9
9
|
def has_required?
|
10
10
|
false
|
11
11
|
end
|
@@ -10,10 +10,8 @@ module SimpleForm
|
|
10
10
|
# Texts can be translated using i18n in "simple_form.yes" and
|
11
11
|
# "simple_form.no" keys. See the example locale file.
|
12
12
|
def self.boolean_collection
|
13
|
-
|
14
|
-
[
|
15
|
-
[I18n.t(:"simple_form.no", default: 'No'), false] ]
|
16
|
-
end
|
13
|
+
[ [I18n.t(:"simple_form.yes", default: 'Yes'), true],
|
14
|
+
[I18n.t(:"simple_form.no", default: 'No'), false] ]
|
17
15
|
end
|
18
16
|
|
19
17
|
def input(wrapper_options = nil)
|
@@ -41,7 +39,7 @@ module SimpleForm
|
|
41
39
|
end
|
42
40
|
|
43
41
|
def has_required?
|
44
|
-
super && (input_options[:include_blank] || input_options[:prompt] || multiple?)
|
42
|
+
super && (input_options[:include_blank] || input_options[:prompt].present? || multiple?)
|
45
43
|
end
|
46
44
|
|
47
45
|
# Check if :include_blank must be included by default.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module SimpleForm
|
3
|
+
module Inputs
|
4
|
+
class RichTextAreaInput < Base
|
5
|
+
def input(wrapper_options = nil)
|
6
|
+
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
7
|
+
|
8
|
+
@builder.rich_text_area(attribute_name, merged_input_options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/simple_form/tags.rb
CHANGED
@@ -48,7 +48,9 @@ module SimpleForm
|
|
48
48
|
private
|
49
49
|
|
50
50
|
def render_component(builder)
|
51
|
-
|
51
|
+
label_class = "#{@options[:item_label_class]} collection_radio_buttons".strip
|
52
|
+
|
53
|
+
builder.radio_button + builder.label(class: label_class)
|
52
54
|
end
|
53
55
|
end
|
54
56
|
|
@@ -62,7 +64,9 @@ module SimpleForm
|
|
62
64
|
private
|
63
65
|
|
64
66
|
def render_component(builder)
|
65
|
-
|
67
|
+
label_class = "#{@options[:item_label_class]} collection_check_boxes".strip
|
68
|
+
|
69
|
+
builder.check_box + builder.label(class: label_class)
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
data/lib/simple_form/version.rb
CHANGED
@@ -28,11 +28,16 @@ module SimpleForm
|
|
28
28
|
css += SimpleForm.additional_classes_for(:wrapper) do
|
29
29
|
input.additional_classes + [input.input_class]
|
30
30
|
end
|
31
|
-
css << (
|
32
|
-
css << (
|
33
|
-
css << (
|
31
|
+
css << html_class(:error_class, options) { input.has_errors? }
|
32
|
+
css << html_class(:hint_class, options) { input.has_hint? }
|
33
|
+
css << html_class(:valid_class, options) { input.valid? }
|
34
34
|
css.compact
|
35
35
|
end
|
36
|
+
|
37
|
+
def html_class(key, options)
|
38
|
+
css = (options[:"wrapper_#{key}"] || @defaults[key])
|
39
|
+
css if css && yield
|
40
|
+
end
|
36
41
|
end
|
37
42
|
end
|
38
43
|
end
|
@@ -45,8 +45,17 @@ class BuilderTest < ActionView::TestCase
|
|
45
45
|
|
46
46
|
test "collection radio sanitizes collection values for labels correctly" do
|
47
47
|
with_collection_radio_buttons @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
|
48
|
-
|
49
|
-
|
48
|
+
|
49
|
+
# Rails 6 changed the way it sanitizes the values
|
50
|
+
# https://github.com/rails/rails/blob/6-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
51
|
+
# https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
52
|
+
if ActionView::VERSION::MAJOR == 5
|
53
|
+
assert_select 'label.collection_radio_buttons[for=user_name_099]', '$0.99'
|
54
|
+
assert_select 'label.collection_radio_buttons[for=user_name_199]', '$1.99'
|
55
|
+
else
|
56
|
+
assert_select 'label.collection_radio_buttons[for=user_name_0_99]', '$0.99'
|
57
|
+
assert_select 'label.collection_radio_buttons[for=user_name_1_99]', '$1.99'
|
58
|
+
end
|
50
59
|
end
|
51
60
|
|
52
61
|
test "collection radio checks the correct value to local variables" do
|
@@ -292,8 +301,17 @@ class BuilderTest < ActionView::TestCase
|
|
292
301
|
|
293
302
|
test "collection check box sanitizes collection values for labels correctly" do
|
294
303
|
with_collection_check_boxes @user, :name, ['$0.99', '$1.99'], :to_s, :to_s
|
295
|
-
|
296
|
-
|
304
|
+
|
305
|
+
# Rails 6 changed the way it sanitizes the values
|
306
|
+
# https://github.com/rails/rails/blob/6-0-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
307
|
+
# https://github.com/rails/rails/blob/5-2-stable/actionview/lib/action_view/helpers/tags/base.rb#L141
|
308
|
+
if ActionView::VERSION::MAJOR == 5
|
309
|
+
assert_select 'label.collection_check_boxes[for=user_name_099]', '$0.99'
|
310
|
+
assert_select 'label.collection_check_boxes[for=user_name_199]', '$1.99'
|
311
|
+
else
|
312
|
+
assert_select 'label.collection_check_boxes[for=user_name_0_99]', '$0.99'
|
313
|
+
assert_select 'label.collection_check_boxes[for=user_name_1_99]', '$1.99'
|
314
|
+
end
|
297
315
|
end
|
298
316
|
|
299
317
|
test "collection check box checks the correct value to local variables" do
|
@@ -4,10 +4,6 @@ require 'test_helper'
|
|
4
4
|
|
5
5
|
# Isolated tests for label without triggering f.label.
|
6
6
|
class IsolatedLabelTest < ActionView::TestCase
|
7
|
-
setup do
|
8
|
-
SimpleForm::Inputs::Base.reset_i18n_cache :translate_required_html
|
9
|
-
end
|
10
|
-
|
11
7
|
def with_label_for(object, attribute_name, type, options = {})
|
12
8
|
with_concat_form_for(object) do |f|
|
13
9
|
options[:reflection] = Association.new(Company, :company, {}) if options.delete(:setup_association)
|
@@ -243,4 +243,10 @@ class AssociationTest < ActionView::TestCase
|
|
243
243
|
assert_equal({ as: :check_boxes, collection_wrapper_tag: :ul, item_wrapper_tag: :li },
|
244
244
|
options)
|
245
245
|
end
|
246
|
+
|
247
|
+
test 'builder with group select considers multiple select by default' do
|
248
|
+
with_association_for @user, :tags, as: :grouped_select, group_method: :group_method
|
249
|
+
|
250
|
+
assert_select 'select[multiple="multiple"].grouped_select'
|
251
|
+
end
|
246
252
|
end
|
@@ -239,31 +239,29 @@ class FormBuilderTest < ActionView::TestCase
|
|
239
239
|
assert_select 'form select#user_updated_at_1i.datetime'
|
240
240
|
end
|
241
241
|
|
242
|
-
test 'builder generates file for
|
243
|
-
|
244
|
-
|
245
|
-
@user.avatar.expect(:!, false)
|
246
|
-
|
247
|
-
with_form_for @user, :avatar
|
248
|
-
assert_select 'form input#user_avatar.file'
|
242
|
+
test 'builder generates file input for ActiveStorage >= 5.2 and Refile >= 0.2.0 <= 0.4.0' do
|
243
|
+
with_form_for UserWithAttachment.build, :avatar
|
244
|
+
assert_select 'form input#user_with_attachment_avatar.file'
|
249
245
|
end
|
250
246
|
|
251
|
-
test 'builder generates file for
|
252
|
-
|
253
|
-
|
254
|
-
|
247
|
+
test 'builder generates file input for ActiveStorage::Attached::Many' do
|
248
|
+
with_form_for UserWithAttachment.build, :avatars
|
249
|
+
assert_select 'form input#user_with_attachment_avatars.file'
|
250
|
+
end
|
255
251
|
|
256
|
-
|
257
|
-
|
252
|
+
test 'builder generates file input for Refile >= 0.3.0 and CarrierWave >= 0.2.2' do
|
253
|
+
with_form_for UserWithAttachment.build, :cover
|
254
|
+
assert_select 'form input#user_with_attachment_cover.file'
|
258
255
|
end
|
259
256
|
|
260
|
-
test 'builder generates file for
|
261
|
-
|
262
|
-
|
263
|
-
|
257
|
+
test 'builder generates file input for Refile >= 0.4.0 and Shrine >= 0.9.0' do
|
258
|
+
with_form_for UserWithAttachment.build, :profile_image
|
259
|
+
assert_select 'form input#user_with_attachment_profile_image.file'
|
260
|
+
end
|
264
261
|
|
265
|
-
|
266
|
-
|
262
|
+
test 'builder generates file input for Paperclip ~> 2.0' do
|
263
|
+
with_form_for UserWithAttachment.build, :portrait
|
264
|
+
assert_select 'form input#user_with_attachment_portrait.file'
|
267
265
|
end
|
268
266
|
|
269
267
|
test 'build generates select if a collection is given' do
|
@@ -19,7 +19,7 @@ class LabelTest < ActionView::TestCase
|
|
19
19
|
assert_select 'label.string[for=user_name]', /Name/
|
20
20
|
end
|
21
21
|
|
22
|
-
test 'builder generates a label for the boolean
|
22
|
+
test 'builder generates a label for the boolean attribute' do
|
23
23
|
with_label_for @user, :name, as: :boolean
|
24
24
|
assert_select 'label.boolean[for=user_name]', /Name/
|
25
25
|
assert_no_select 'label[as=boolean]'
|
@@ -59,6 +59,13 @@ class WrapperTest < ActionView::TestCase
|
|
59
59
|
assert_no_select 'input.is-invalid'
|
60
60
|
end
|
61
61
|
|
62
|
+
test 'wrapper does not determine if valid class is needed when it is set to nil' do
|
63
|
+
@user.instance_eval { undef errors }
|
64
|
+
with_form_for @user, :name, wrapper: custom_wrapper_with_input_valid_class(valid_class: nil)
|
65
|
+
|
66
|
+
assert_no_select 'div.field_without_errors'
|
67
|
+
end
|
68
|
+
|
62
69
|
test 'wrapper adds hint class for attribute with a hint' do
|
63
70
|
with_form_for @user, :name, hint: 'hint'
|
64
71
|
assert_select 'div.field_with_hint'
|
@@ -161,7 +168,7 @@ class WrapperTest < ActionView::TestCase
|
|
161
168
|
test 'custom wrappers can have full error message on attributes' do
|
162
169
|
swap_wrapper :default, custom_wrapper_with_full_error do
|
163
170
|
with_form_for @user, :name
|
164
|
-
assert_select 'span.error', "Name cannot be blank"
|
171
|
+
assert_select 'span.error', "Super User Name! cannot be blank"
|
165
172
|
end
|
166
173
|
end
|
167
174
|
|
@@ -3,10 +3,6 @@
|
|
3
3
|
require 'test_helper'
|
4
4
|
|
5
5
|
class CollectionCheckBoxesInputTest < ActionView::TestCase
|
6
|
-
setup do
|
7
|
-
SimpleForm::Inputs::CollectionCheckBoxesInput.reset_i18n_cache :boolean_collection
|
8
|
-
end
|
9
|
-
|
10
6
|
test 'input check boxes does not include for attribute by default' do
|
11
7
|
with_input_for @user, :gender, :check_boxes, collection: %i[male female]
|
12
8
|
assert_select 'label'
|
@@ -316,4 +312,12 @@ class CollectionCheckBoxesInputTest < ActionView::TestCase
|
|
316
312
|
assert_select 'span.checkbox > label', '200'
|
317
313
|
end
|
318
314
|
end
|
315
|
+
|
316
|
+
test 'input check boxes with inline style support label custom classes' do
|
317
|
+
swap SimpleForm, boolean_style: :inline do
|
318
|
+
with_input_for @user, :gender, :check_boxes, collection: %i[male female], item_label_class: 'beautiful-label'
|
319
|
+
|
320
|
+
assert_select 'label.beautiful-label', count: 2
|
321
|
+
end
|
322
|
+
end
|
319
323
|
end
|