formtastic 3.1.3 → 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 +7 -0
- data/.gitattributes +1 -0
- data/.github/workflows/test.yml +61 -0
- data/.gitignore +3 -2
- data/CHANGELOG.md +61 -0
- data/Gemfile.lock +140 -0
- data/MIT-LICENSE +1 -1
- data/{README.textile → README.md} +183 -167
- data/RELEASE_PROCESS +3 -1
- data/Rakefile +20 -1
- data/app/assets/stylesheets/formtastic.css +1 -1
- data/bin/appraisal +8 -0
- data/formtastic.gemspec +12 -16
- data/gemfiles/rails_6.0/Gemfile +5 -0
- data/gemfiles/rails_6.1/Gemfile +5 -0
- data/gemfiles/rails_7.0/Gemfile +5 -0
- data/gemfiles/rails_7.1/Gemfile +5 -0
- data/gemfiles/rails_edge/Gemfile +13 -0
- data/lib/formtastic/action_class_finder.rb +1 -0
- data/lib/formtastic/actions/base.rb +1 -0
- data/lib/formtastic/actions/button_action.rb +1 -0
- data/lib/formtastic/actions/buttonish.rb +1 -0
- data/lib/formtastic/actions/input_action.rb +1 -0
- data/lib/formtastic/actions/link_action.rb +1 -0
- data/lib/formtastic/actions.rb +7 -3
- data/lib/formtastic/deprecation.rb +2 -38
- data/lib/formtastic/engine.rb +4 -1
- data/lib/formtastic/form_builder.rb +12 -24
- data/lib/formtastic/helpers/action_helper.rb +2 -48
- data/lib/formtastic/helpers/actions_helper.rb +1 -0
- data/lib/formtastic/helpers/enum.rb +14 -0
- data/lib/formtastic/helpers/errors_helper.rb +3 -2
- data/lib/formtastic/helpers/fieldset_wrapper.rb +14 -9
- data/lib/formtastic/helpers/file_column_detection.rb +1 -0
- data/lib/formtastic/helpers/form_helper.rb +2 -1
- data/lib/formtastic/helpers/input_helper.rb +20 -76
- data/lib/formtastic/helpers/inputs_helper.rb +29 -23
- data/lib/formtastic/helpers/reflection.rb +1 -0
- data/lib/formtastic/helpers.rb +2 -2
- data/lib/formtastic/html_attributes.rb +1 -0
- data/lib/formtastic/i18n.rb +2 -1
- data/lib/formtastic/input_class_finder.rb +1 -0
- data/lib/formtastic/inputs/base/associations.rb +1 -0
- data/lib/formtastic/inputs/base/choices.rb +3 -2
- data/lib/formtastic/inputs/base/collections.rb +46 -10
- data/lib/formtastic/inputs/base/database.rb +5 -7
- data/lib/formtastic/inputs/base/datetime_pickerish.rb +1 -0
- data/lib/formtastic/inputs/base/errors.rb +7 -6
- data/lib/formtastic/inputs/base/fileish.rb +1 -0
- data/lib/formtastic/inputs/base/hints.rb +2 -1
- data/lib/formtastic/inputs/base/html.rb +9 -7
- data/lib/formtastic/inputs/base/labelling.rb +3 -2
- data/lib/formtastic/inputs/base/naming.rb +5 -4
- data/lib/formtastic/inputs/base/numeric.rb +1 -0
- data/lib/formtastic/inputs/base/options.rb +3 -3
- data/lib/formtastic/inputs/base/placeholder.rb +1 -0
- data/lib/formtastic/inputs/base/stringish.rb +1 -0
- data/lib/formtastic/inputs/base/timeish.rb +9 -4
- data/lib/formtastic/inputs/base/validations.rb +39 -12
- data/lib/formtastic/inputs/base/wrapping.rb +1 -0
- data/lib/formtastic/inputs/base.rb +3 -2
- data/lib/formtastic/inputs/boolean_input.rb +2 -1
- data/lib/formtastic/inputs/check_boxes_input.rb +15 -6
- data/lib/formtastic/inputs/color_input.rb +1 -1
- data/lib/formtastic/inputs/country_input.rb +4 -1
- data/lib/formtastic/inputs/datalist_input.rb +1 -0
- data/lib/formtastic/inputs/date_picker_input.rb +1 -0
- data/lib/formtastic/inputs/date_select_input.rb +1 -0
- data/lib/formtastic/inputs/datetime_picker_input.rb +1 -0
- data/lib/formtastic/inputs/datetime_select_input.rb +1 -0
- data/lib/formtastic/inputs/email_input.rb +1 -0
- data/lib/formtastic/inputs/file_input.rb +1 -0
- data/lib/formtastic/inputs/hidden_input.rb +3 -2
- data/lib/formtastic/inputs/number_input.rb +1 -0
- data/lib/formtastic/inputs/password_input.rb +1 -0
- data/lib/formtastic/inputs/phone_input.rb +1 -0
- data/lib/formtastic/inputs/radio_input.rb +21 -0
- data/lib/formtastic/inputs/range_input.rb +1 -0
- data/lib/formtastic/inputs/search_input.rb +1 -0
- data/lib/formtastic/inputs/select_input.rb +30 -1
- data/lib/formtastic/inputs/string_input.rb +1 -0
- data/lib/formtastic/inputs/text_input.rb +1 -0
- data/lib/formtastic/inputs/time_picker_input.rb +1 -0
- data/lib/formtastic/inputs/time_select_input.rb +1 -0
- data/lib/formtastic/inputs/time_zone_input.rb +17 -6
- data/lib/formtastic/inputs/url_input.rb +1 -0
- data/lib/formtastic/inputs.rb +33 -29
- data/lib/formtastic/localized_string.rb +1 -0
- data/lib/formtastic/localizer.rb +21 -22
- data/lib/formtastic/namespaced_class_finder.rb +8 -9
- data/lib/formtastic/version.rb +2 -1
- data/lib/formtastic.rb +10 -11
- data/lib/generators/formtastic/form/form_generator.rb +2 -1
- data/lib/generators/formtastic/input/input_generator.rb +47 -0
- data/lib/generators/formtastic/install/install_generator.rb +1 -0
- data/lib/generators/templates/formtastic.rb +15 -13
- data/lib/generators/templates/input.rb +19 -0
- data/sample/basic_inputs.html +1 -1
- data/script/integration-template.rb +73 -0
- data/script/integration.sh +19 -0
- data/spec/action_class_finder_spec.rb +2 -1
- data/spec/actions/button_action_spec.rb +21 -20
- data/spec/actions/generic_action_spec.rb +134 -133
- data/spec/actions/input_action_spec.rb +20 -19
- data/spec/actions/link_action_spec.rb +30 -29
- data/spec/builder/custom_builder_spec.rb +39 -22
- data/spec/builder/error_proc_spec.rb +6 -5
- data/spec/builder/semantic_fields_for_spec.rb +46 -45
- data/spec/fast_spec_helper.rb +13 -0
- data/spec/generators/formtastic/form/form_generator_spec.rb +33 -32
- data/spec/generators/formtastic/input/input_generator_spec.rb +125 -0
- data/spec/generators/formtastic/install/install_generator_spec.rb +10 -9
- data/spec/helpers/action_helper_spec.rb +329 -10
- data/spec/helpers/actions_helper_spec.rb +43 -42
- data/spec/helpers/form_helper_spec.rb +45 -38
- data/spec/helpers/input_helper_spec.rb +976 -2
- data/spec/helpers/inputs_helper_spec.rb +217 -202
- data/spec/helpers/reflection_helper_spec.rb +7 -6
- data/spec/helpers/semantic_errors_helper_spec.rb +26 -25
- data/spec/i18n_spec.rb +30 -29
- data/spec/input_class_finder_spec.rb +2 -1
- data/spec/inputs/base/collections_spec.rb +78 -0
- data/spec/inputs/base/validations_spec.rb +481 -0
- data/spec/inputs/boolean_input_spec.rb +73 -72
- data/spec/inputs/check_boxes_input_spec.rb +169 -121
- data/spec/inputs/color_input_spec.rb +53 -64
- data/spec/inputs/country_input_spec.rb +23 -22
- data/spec/inputs/custom_input_spec.rb +3 -6
- data/spec/inputs/datalist_input_spec.rb +3 -2
- data/spec/inputs/date_picker_input_spec.rb +114 -113
- data/spec/inputs/date_select_input_spec.rb +76 -61
- data/spec/inputs/datetime_picker_input_spec.rb +123 -122
- data/spec/inputs/datetime_select_input_spec.rb +85 -68
- data/spec/inputs/email_input_spec.rb +17 -16
- data/spec/inputs/file_input_spec.rb +18 -17
- data/spec/inputs/hidden_input_spec.rb +32 -31
- data/spec/inputs/include_blank_spec.rb +10 -9
- data/spec/inputs/label_spec.rb +26 -25
- data/spec/inputs/number_input_spec.rb +212 -211
- data/spec/inputs/password_input_spec.rb +17 -16
- data/spec/inputs/phone_input_spec.rb +17 -16
- data/spec/inputs/placeholder_spec.rb +18 -17
- data/spec/inputs/radio_input_spec.rb +92 -65
- data/spec/inputs/range_input_spec.rb +136 -135
- data/spec/inputs/readonly_spec.rb +51 -0
- data/spec/inputs/search_input_spec.rb +16 -15
- data/spec/inputs/select_input_spec.rb +209 -102
- data/spec/inputs/string_input_spec.rb +51 -50
- data/spec/inputs/text_input_spec.rb +34 -33
- data/spec/inputs/time_picker_input_spec.rb +115 -114
- data/spec/inputs/time_select_input_spec.rb +84 -70
- data/spec/inputs/time_zone_input_spec.rb +58 -31
- data/spec/inputs/url_input_spec.rb +17 -16
- data/spec/inputs/with_options_spec.rb +9 -8
- data/spec/localizer_spec.rb +18 -17
- data/spec/namespaced_class_finder_spec.rb +18 -6
- data/spec/schema.rb +22 -0
- data/spec/spec_helper.rb +172 -260
- data/spec/support/custom_macros.rb +74 -76
- data/spec/support/deprecation.rb +2 -1
- data/spec/support/shared_examples.rb +2 -1233
- data/spec/support/specialized_class_finder_shared_example.rb +1 -0
- data/spec/support/test_environment.rb +24 -9
- metadata +78 -170
- data/.travis.yml +0 -29
- data/Appraisals +0 -29
- data/CHANGELOG +0 -39
- data/DEPRECATIONS +0 -49
- data/gemfiles/rails_3.2.gemfile +0 -7
- data/gemfiles/rails_4.0.4.gemfile +0 -7
- data/gemfiles/rails_4.1.gemfile +0 -7
- data/gemfiles/rails_4.2.gemfile +0 -7
- data/gemfiles/rails_4.gemfile +0 -7
- data/gemfiles/rails_edge.gemfile +0 -10
- data/lib/formtastic/util.rb +0 -57
- data/spec/helpers/namespaced_action_helper_spec.rb +0 -43
- data/spec/helpers/namespaced_input_helper_spec.rb +0 -36
- data/spec/support/deferred_garbage_collection.rb +0 -21
- data/spec/util_spec.rb +0 -66
data/lib/formtastic/inputs.rb
CHANGED
|
@@ -1,39 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Formtastic
|
|
2
3
|
module Inputs
|
|
3
4
|
extend ActiveSupport::Autoload
|
|
4
5
|
|
|
5
6
|
autoload :Base
|
|
6
7
|
autoload :Basic
|
|
7
|
-
autoload :BooleanInput
|
|
8
|
-
autoload :CheckBoxesInput
|
|
9
|
-
autoload :ColorInput
|
|
10
|
-
autoload :CountryInput
|
|
11
|
-
autoload :DatalistInput
|
|
12
|
-
autoload :DateInput
|
|
13
|
-
autoload :DatePickerInput
|
|
14
|
-
autoload :DatetimePickerInput
|
|
15
|
-
autoload :DateSelectInput
|
|
16
|
-
autoload :DatetimeInput
|
|
17
|
-
autoload :DatetimeSelectInput
|
|
18
|
-
autoload :EmailInput
|
|
19
|
-
autoload :FileInput
|
|
20
|
-
autoload :HiddenInput
|
|
21
|
-
autoload :NumberInput
|
|
22
|
-
autoload :NumericInput
|
|
23
|
-
autoload :PasswordInput
|
|
24
|
-
autoload :PhoneInput
|
|
25
|
-
autoload :RadioInput
|
|
26
|
-
autoload :RangeInput
|
|
27
|
-
autoload :SearchInput
|
|
28
|
-
autoload :SelectInput
|
|
29
|
-
autoload :StringInput
|
|
30
|
-
autoload :TextInput
|
|
31
|
-
autoload :TimeInput
|
|
32
|
-
autoload :TimePickerInput
|
|
33
|
-
autoload :TimeSelectInput
|
|
34
|
-
autoload :TimeZoneInput
|
|
35
8
|
autoload :Timeish
|
|
36
|
-
|
|
9
|
+
|
|
10
|
+
eager_autoload do
|
|
11
|
+
autoload :BooleanInput
|
|
12
|
+
autoload :CheckBoxesInput
|
|
13
|
+
autoload :ColorInput
|
|
14
|
+
autoload :CountryInput
|
|
15
|
+
autoload :DatalistInput
|
|
16
|
+
autoload :DateInput
|
|
17
|
+
autoload :DatePickerInput
|
|
18
|
+
autoload :DatetimePickerInput
|
|
19
|
+
autoload :DateSelectInput
|
|
20
|
+
autoload :DatetimeInput
|
|
21
|
+
autoload :DatetimeSelectInput
|
|
22
|
+
autoload :EmailInput
|
|
23
|
+
autoload :FileInput
|
|
24
|
+
autoload :HiddenInput
|
|
25
|
+
autoload :NumberInput
|
|
26
|
+
autoload :NumericInput
|
|
27
|
+
autoload :PasswordInput
|
|
28
|
+
autoload :PhoneInput
|
|
29
|
+
autoload :RadioInput
|
|
30
|
+
autoload :RangeInput
|
|
31
|
+
autoload :SearchInput
|
|
32
|
+
autoload :SelectInput
|
|
33
|
+
autoload :StringInput
|
|
34
|
+
autoload :TextInput
|
|
35
|
+
autoload :TimeInput
|
|
36
|
+
autoload :TimePickerInput
|
|
37
|
+
autoload :TimeSelectInput
|
|
38
|
+
autoload :TimeZoneInput
|
|
39
|
+
autoload :UrlInput
|
|
40
|
+
end
|
|
37
41
|
end
|
|
38
42
|
end
|
|
39
43
|
|
data/lib/formtastic/localizer.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Formtastic
|
|
2
|
-
# Implementation for looking up localized values within Formtastic using I18n, if no
|
|
3
|
+
# Implementation for looking up localized values within Formtastic using I18n, if no
|
|
3
4
|
# explicit value (like the `:label` option) is set and I18n-lookups are enabled in the
|
|
4
5
|
# configuration.
|
|
5
6
|
#
|
|
@@ -28,50 +29,50 @@ module Formtastic
|
|
|
28
29
|
def get(key)
|
|
29
30
|
cache[key]
|
|
30
31
|
end
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
def has_key?(key)
|
|
33
34
|
cache.has_key?(key)
|
|
34
35
|
end
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
def set(key, result)
|
|
37
38
|
cache[key] = result
|
|
38
39
|
end
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
def cache
|
|
41
42
|
@cache ||= {}
|
|
42
43
|
end
|
|
43
|
-
|
|
44
|
+
|
|
44
45
|
def clear!
|
|
45
46
|
cache.clear
|
|
46
47
|
end
|
|
47
48
|
end
|
|
48
|
-
|
|
49
|
+
|
|
49
50
|
attr_accessor :builder
|
|
50
|
-
|
|
51
|
+
|
|
51
52
|
def self.cache
|
|
52
53
|
@cache ||= Cache.new
|
|
53
54
|
end
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
def initialize(current_builder)
|
|
56
|
-
self.builder = current_builder
|
|
57
|
+
self.builder = current_builder
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
def localize(key, value, type, options = {}) # @private
|
|
60
61
|
key = value if value.is_a?(::Symbol)
|
|
61
|
-
|
|
62
|
+
|
|
62
63
|
if value.is_a?(::String)
|
|
63
64
|
escape_html_entities(value)
|
|
64
65
|
else
|
|
65
66
|
use_i18n = value.nil? ? i18n_lookups_by_default : (value != false)
|
|
66
67
|
use_cache = i18n_cache_lookups
|
|
67
68
|
cache = self.class.cache
|
|
68
|
-
|
|
69
|
+
|
|
69
70
|
if use_i18n
|
|
70
71
|
model_name, nested_model_name = normalize_model_name(builder.model_name.underscore)
|
|
71
72
|
|
|
72
73
|
action_name = builder.template.params[:action].to_s rescue ''
|
|
73
74
|
attribute_name = key.to_s
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
# look in the cache first
|
|
76
77
|
if use_cache
|
|
77
78
|
cache_key = [::I18n.locale, action_name, model_name, nested_model_name, attribute_name, key, value, type, options]
|
|
@@ -86,7 +87,7 @@ module Formtastic
|
|
|
86
87
|
i18n_path.gsub!('%{model}', model_name)
|
|
87
88
|
i18n_path.gsub!('%{nested_model}', nested_model_name) unless nested_model_name.nil?
|
|
88
89
|
i18n_path.gsub!('%{attribute}', attribute_name)
|
|
89
|
-
i18n_path.
|
|
90
|
+
i18n_path.tr!('..', '.')
|
|
90
91
|
i18n_path.to_sym
|
|
91
92
|
end
|
|
92
93
|
defaults << ''
|
|
@@ -101,9 +102,9 @@ module Formtastic
|
|
|
101
102
|
# This is effectively what Rails label helper does for i18n lookup
|
|
102
103
|
options[:scope] = [:helpers, type]
|
|
103
104
|
options[:default] = defaults
|
|
104
|
-
i18n_value = ::I18n.t(default_key, options)
|
|
105
|
+
i18n_value = ::I18n.t(default_key, **options)
|
|
105
106
|
end
|
|
106
|
-
|
|
107
|
+
|
|
107
108
|
# save the result to the cache
|
|
108
109
|
result = (i18n_value.is_a?(::String) && i18n_value.present?) ? escape_html_entities(i18n_value) : nil
|
|
109
110
|
cache.set(cache_key, result) if use_cache
|
|
@@ -115,16 +116,14 @@ module Formtastic
|
|
|
115
116
|
protected
|
|
116
117
|
|
|
117
118
|
def normalize_model_name(name)
|
|
118
|
-
if
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
elsif name =~ /(.+)\[(.+)\]/
|
|
122
|
-
# Rails 3 (and 3.1?) nested builder case with :post rather than @post
|
|
119
|
+
if name =~ /(.+)\[(.+)\]/
|
|
120
|
+
# Nested builder case with :post rather than @post
|
|
121
|
+
# TODO: check if this is no longer required with a minimum of Rails 4.1
|
|
123
122
|
[$1, $2]
|
|
124
123
|
elsif builder.respond_to?(:options) && builder.options.key?(:as)
|
|
125
124
|
[builder.options[:as].to_s]
|
|
126
125
|
elsif builder.respond_to?(:options) && builder.options.key?(:parent_builder)
|
|
127
|
-
# Rails 3.0 nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
|
|
126
|
+
# Rails 3.0+ nested builder work-around case, where :parent_builder is provided by f.semantic_form_for
|
|
128
127
|
[builder.options[:parent_builder].object_name.to_s, name]
|
|
129
128
|
else
|
|
130
129
|
# Non-nested case
|
|
@@ -143,7 +142,7 @@ module Formtastic
|
|
|
143
142
|
def i18n_lookups_by_default
|
|
144
143
|
builder.i18n_lookups_by_default
|
|
145
144
|
end
|
|
146
|
-
|
|
145
|
+
|
|
147
146
|
def i18n_cache_lookups
|
|
148
147
|
builder.i18n_cache_lookups
|
|
149
148
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Formtastic
|
|
2
3
|
# This class implements class resolution in a namespace chain. It
|
|
3
4
|
# is used both by Formtastic::Helpers::InputHelper and
|
|
@@ -29,7 +30,11 @@ module Formtastic
|
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def self.use_const_defined?
|
|
32
|
-
defined?(Rails) && ::Rails.application && ::Rails.application.config.eager_load
|
|
33
|
+
defined?(Rails) && ::Rails.application && ::Rails.application.config.respond_to?(:eager_load) && ::Rails.application.config.eager_load
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.finder_method
|
|
37
|
+
@finder_method ||= use_const_defined? ? :find_with_const_defined : :find_by_trying
|
|
33
38
|
end
|
|
34
39
|
|
|
35
40
|
# @param namespaces [Array<Module>]
|
|
@@ -66,14 +71,8 @@ module Formtastic
|
|
|
66
71
|
|
|
67
72
|
private
|
|
68
73
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
find_with_const_defined(class_name)
|
|
72
|
-
end
|
|
73
|
-
else
|
|
74
|
-
def finder(class_name) # @private
|
|
75
|
-
find_by_trying(class_name)
|
|
76
|
-
end
|
|
74
|
+
def finder(class_name) # @private
|
|
75
|
+
send(self.class.finder_method, class_name)
|
|
77
76
|
end
|
|
78
77
|
|
|
79
78
|
# Looks up the given class name in the configured namespaces in order,
|
data/lib/formtastic/version.rb
CHANGED
data/lib/formtastic.rb
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'formtastic/engine' if defined?(::Rails)
|
|
3
4
|
|
|
4
5
|
module Formtastic
|
|
5
6
|
extend ActiveSupport::Autoload
|
|
6
7
|
|
|
7
|
-
autoload :FormBuilder
|
|
8
8
|
autoload :Helpers
|
|
9
9
|
autoload :HtmlAttributes
|
|
10
|
-
autoload :I18n
|
|
11
|
-
autoload :Inputs
|
|
12
|
-
autoload :Actions
|
|
13
10
|
autoload :LocalizedString
|
|
14
11
|
autoload :Localizer
|
|
15
|
-
autoload :Util
|
|
16
12
|
autoload :NamespacedClassFinder
|
|
17
13
|
autoload :InputClassFinder
|
|
18
14
|
autoload :ActionClassFinder
|
|
19
15
|
autoload :Deprecation
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
deprecation.warn("Support for Rails < #{Util.minimum_version_of_rails} will be dropped")
|
|
17
|
+
eager_autoload do
|
|
18
|
+
autoload :I18n
|
|
19
|
+
autoload :FormBuilder
|
|
20
|
+
autoload :Inputs
|
|
21
|
+
autoload :Actions
|
|
27
22
|
end
|
|
28
23
|
|
|
29
24
|
# @public
|
|
@@ -42,4 +37,8 @@ module Formtastic
|
|
|
42
37
|
class UnsupportedMethodForAction < ArgumentError
|
|
43
38
|
end
|
|
44
39
|
|
|
40
|
+
# @private
|
|
41
|
+
class UnsupportedEnumCollection < NameError
|
|
42
|
+
end
|
|
43
|
+
|
|
45
44
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
module Formtastic
|
|
3
4
|
# Generates a Formtastic form partial based on an existing model. It will not overwrite existing
|
|
4
5
|
# files without confirmation.
|
|
@@ -75,7 +76,7 @@ module Formtastic
|
|
|
75
76
|
# Skips Active Record Timestamps.
|
|
76
77
|
def content_columns
|
|
77
78
|
model.content_columns.select do |column|
|
|
78
|
-
!Formtastic::
|
|
79
|
+
!Formtastic::FormBuilder.skipped_columns.include? column.name.to_sym
|
|
79
80
|
end
|
|
80
81
|
end
|
|
81
82
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Formtastic
|
|
3
|
+
|
|
4
|
+
# Modify existing inputs, subclass them, or create your own from scratch.
|
|
5
|
+
# @example
|
|
6
|
+
# !!!shell
|
|
7
|
+
# $ rails generate formtastic:input HatSize
|
|
8
|
+
|
|
9
|
+
# @example Define input name using underscore convention
|
|
10
|
+
# !!!shell
|
|
11
|
+
# $ rails generate formtastic:input hat_size
|
|
12
|
+
|
|
13
|
+
# @example Override an existing input behavior
|
|
14
|
+
# !!!shell
|
|
15
|
+
# $ rails generate formtastic:input string --extend
|
|
16
|
+
|
|
17
|
+
# @example Extend an existing input behavior
|
|
18
|
+
# !!!shell
|
|
19
|
+
# $ rails generate formtastic:input FlexibleText --extend string
|
|
20
|
+
class InputGenerator < Rails::Generators::NamedBase
|
|
21
|
+
|
|
22
|
+
argument :name, :type => :string, :required => true, :banner => 'FILE_NAME'
|
|
23
|
+
|
|
24
|
+
source_root File.expand_path('../../../templates', __FILE__)
|
|
25
|
+
|
|
26
|
+
class_option :extend
|
|
27
|
+
|
|
28
|
+
def create
|
|
29
|
+
normalize_file_name
|
|
30
|
+
define_extension_sentence
|
|
31
|
+
template "input.rb", "app/inputs/#{name.underscore}_input.rb"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def normalize_file_name
|
|
37
|
+
name.chomp!("Input") if name.ends_with?("Input")
|
|
38
|
+
name.chomp!("_input") if name.ends_with?("_input")
|
|
39
|
+
name.chomp!("input") if name.ends_with?("input")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def define_extension_sentence
|
|
43
|
+
@extension_sentence = "< Formtastic::Inputs::#{name.camelize}Input" if options[:extend] == "extend"
|
|
44
|
+
@extension_sentence ||= "< Formtastic::Inputs::#{options[:extend].camelize}Input" if options[:extend]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
# Set the default text field size when input is a string. Default is nil.
|
|
4
5
|
# Formtastic::FormBuilder.default_text_field_size = 50
|
|
@@ -17,15 +18,15 @@
|
|
|
17
18
|
# Defaults to true.
|
|
18
19
|
# Formtastic::FormBuilder.include_blank_for_select_by_default = true
|
|
19
20
|
|
|
20
|
-
# Set the string that will be appended to the labels/fieldsets which are required
|
|
21
|
+
# Set the string that will be appended to the labels/fieldsets which are required.
|
|
21
22
|
# It accepts string or procs and the default is a localized version of
|
|
22
23
|
# '<abbr title="required">*</abbr>'. In other words, if you configure formtastic.required
|
|
23
24
|
# in your locale, it will replace the abbr title properly. But if you don't want to use
|
|
24
|
-
# abbr tag, you can simply give a string as below
|
|
25
|
+
# abbr tag, you can simply give a string as below.
|
|
25
26
|
# Formtastic::FormBuilder.required_string = "(required)"
|
|
26
27
|
|
|
27
|
-
# Set the string that will be appended to the labels/fieldsets which are optional
|
|
28
|
-
# Defaults to an empty string ("") and also accepts procs (see required_string above)
|
|
28
|
+
# Set the string that will be appended to the labels/fieldsets which are optional.
|
|
29
|
+
# Defaults to an empty string ("") and also accepts procs (see required_string above).
|
|
29
30
|
# Formtastic::FormBuilder.optional_string = "(optional)"
|
|
30
31
|
|
|
31
32
|
# Set the way inline errors will be displayed.
|
|
@@ -33,7 +34,7 @@
|
|
|
33
34
|
# Formtastic::FormBuilder.inline_errors = :sentence
|
|
34
35
|
# Formtastic uses the following classes as default for hints, inline_errors and error list
|
|
35
36
|
|
|
36
|
-
# If you override the class here, please ensure to override it in your stylesheets as well
|
|
37
|
+
# If you override the class here, please ensure to override it in your stylesheets as well.
|
|
37
38
|
# Formtastic::FormBuilder.default_hint_class = "inline-hints"
|
|
38
39
|
# Formtastic::FormBuilder.default_inline_error_class = "inline-errors"
|
|
39
40
|
# Formtastic::FormBuilder.default_error_list_class = "errors"
|
|
@@ -70,7 +71,7 @@
|
|
|
70
71
|
# can change it to any class you want.
|
|
71
72
|
# Formtastic::Helpers::FormHelper.default_form_class = 'formtastic'
|
|
72
73
|
|
|
73
|
-
# Formtastic will infer a class name from the model, array, string
|
|
74
|
+
# Formtastic will infer a class name from the model, array, string or symbol you pass to the
|
|
74
75
|
# form builder. You can customize the way that class is presented by overriding
|
|
75
76
|
# this proc.
|
|
76
77
|
# Formtastic::Helpers::FormHelper.default_form_model_class_proc = proc { |model_class_name| model_class_name }
|
|
@@ -85,15 +86,14 @@
|
|
|
85
86
|
# Formtastic::FormBuilder.use_required_attribute = false
|
|
86
87
|
|
|
87
88
|
# You can opt-in to new HTML5 browser validations (for things like email and url inputs) by setting
|
|
88
|
-
# this to true. Doing so will
|
|
89
|
+
# this to true. Doing so will omit the `novalidate` attribute from the `<form>` tag.
|
|
89
90
|
# See http://diveintohtml5.org/forms.html#validation for more info.
|
|
90
91
|
# Formtastic::FormBuilder.perform_browser_validations = true
|
|
91
92
|
|
|
92
93
|
# By creating custom input class finder, you can change how input classes are looked up.
|
|
93
94
|
# For example you can make it to search for TextInputFilter instead of TextInput.
|
|
94
|
-
# See
|
|
95
|
-
#
|
|
96
|
-
Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
|
|
95
|
+
# See https://github.com/formtastic/formtastic/wiki/Custom-Class-Finders
|
|
96
|
+
# Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
|
|
97
97
|
|
|
98
98
|
# Define custom namespaces in which to look up your Input classes. Default is
|
|
99
99
|
# to look up in the global scope and in Formtastic::Inputs.
|
|
@@ -101,10 +101,12 @@ Formtastic::FormBuilder.input_class_finder = Formtastic::InputClassFinder
|
|
|
101
101
|
|
|
102
102
|
# By creating custom action class finder, you can change how action classes are looked up.
|
|
103
103
|
# For example you can make it to search for MyButtonAction instead of ButtonAction.
|
|
104
|
-
# See
|
|
105
|
-
#
|
|
106
|
-
Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder
|
|
104
|
+
# See https://github.com/formtastic/formtastic/wiki/Custom-Class-Finders
|
|
105
|
+
# Formtastic::FormBuilder.action_class_finder = Formtastic::ActionClassFinder
|
|
107
106
|
|
|
108
107
|
# Define custom namespaces in which to look up your Action classes. Default is
|
|
109
108
|
# to look up in the global scope and in Formtastic::Actions.
|
|
110
109
|
# Formtastic::FormBuilder.action_namespaces = [ ::Object, ::MyActionsModule, ::Formtastic::Actions ]
|
|
110
|
+
|
|
111
|
+
# Which columns to skip when automatically rendering a form without any fields specified.
|
|
112
|
+
# Formtastic::FormBuilder.skipped_columns = [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class <%= name.camelize %>Input <%= @extension_sentence %>
|
|
2
|
+
<%- if !options[:extend] -%>
|
|
3
|
+
include Formtastic::Inputs::Base
|
|
4
|
+
<%- end -%>
|
|
5
|
+
|
|
6
|
+
<%- if !options[:extend] || (options[:extend] == "extend") -%>
|
|
7
|
+
def to_html
|
|
8
|
+
# Add your custom input definition here.
|
|
9
|
+
<%- if options[:extend] == "extend" -%>
|
|
10
|
+
super
|
|
11
|
+
<%- end -%>
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
<%- else -%>
|
|
15
|
+
def input_html_options
|
|
16
|
+
# Add your custom input extension here.
|
|
17
|
+
end
|
|
18
|
+
<%- end -%>
|
|
19
|
+
end
|
data/sample/basic_inputs.html
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<li class="input url stringish optional" id="gem_url_input">
|
|
37
37
|
<label class="label" for="gem_url">URL</label>
|
|
38
38
|
<input id="gem_url" name="gem[url]" type="url">
|
|
39
|
-
<p class="inline-hints">Example: https://github.com/
|
|
39
|
+
<p class="inline-hints">Example: https://github.com/formtastic/formtastic</p>
|
|
40
40
|
</li>
|
|
41
41
|
|
|
42
42
|
<li class="input password stringish required" id="gem_password_input">
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
gem 'formtastic', path: '..'
|
|
3
|
+
gem 'bcrypt', '~> 3.1.7'
|
|
4
|
+
gem 'rails-dom-testing', group: :test
|
|
5
|
+
gem 'rexml', '~> 3.2' # to compensate for missing dependency in selenium-webdriver
|
|
6
|
+
|
|
7
|
+
# to speed up bundle install, reuse the bundle path
|
|
8
|
+
def bundle_path
|
|
9
|
+
File.expand_path ENV.fetch('BUNDLE_PATH', 'vendor/bundle')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
if Rails.version >= '6.2'
|
|
13
|
+
gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails'"
|
|
14
|
+
elsif Rails.version >= '6.1'
|
|
15
|
+
gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails', branch: '6-1-stable'"
|
|
16
|
+
elsif Rails.version >= '6.0'
|
|
17
|
+
gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails', branch: '6-0-stable'"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
### Ensure Dummy App's Ruby version matches the current environments Ruby Version
|
|
21
|
+
ruby_version = "ruby '#{RUBY_VERSION}'"
|
|
22
|
+
gsub_file 'Gemfile', /ruby '\d+.\d+.\d+'/, ruby_version
|
|
23
|
+
|
|
24
|
+
if bundle_install?
|
|
25
|
+
def run_bundle
|
|
26
|
+
previous_bundle_path = bundle_path
|
|
27
|
+
|
|
28
|
+
require "bundler"
|
|
29
|
+
Bundler.with_clean_env do
|
|
30
|
+
system("bundle install --jobs=3 --retry=3 --path=#{previous_bundle_path}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
in_root do
|
|
36
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path('Gemfile')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
formtastic = -> do
|
|
40
|
+
generate(:scaffold, 'user name:string password:digest')
|
|
41
|
+
generate('formtastic:install')
|
|
42
|
+
generate('formtastic:form', 'user name password --force')
|
|
43
|
+
|
|
44
|
+
rails_command('db:migrate')
|
|
45
|
+
|
|
46
|
+
in_root do
|
|
47
|
+
inject_into_class 'app/models/user.rb', 'User', " has_secure_password\n"
|
|
48
|
+
inject_into_file 'app/assets/stylesheets/application.css', " *= require formtastic\n", before: ' *= require_self'
|
|
49
|
+
inject_into_class 'test/controllers/users_controller_test.rb', 'UsersControllerTest', <<-RUBY
|
|
50
|
+
|
|
51
|
+
test "should show form" do
|
|
52
|
+
get edit_user_path(@user)
|
|
53
|
+
|
|
54
|
+
assert_select 'form' do
|
|
55
|
+
assert_select 'li.input.string' do
|
|
56
|
+
assert_select 'input#user_name[type=text]'
|
|
57
|
+
end
|
|
58
|
+
assert_select 'li.input.password' do
|
|
59
|
+
assert_select 'input#user_password[type=password]'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
assert_select 'fieldset.actions' do
|
|
63
|
+
assert_select 'li.action.input_action' do
|
|
64
|
+
assert_select 'input[type=submit]'
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end # test "should show form"
|
|
69
|
+
RUBY
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
after_bundle(&formtastic)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
set -o verbose
|
|
5
|
+
|
|
6
|
+
test_app=dummy
|
|
7
|
+
|
|
8
|
+
rm -rf ${test_app}
|
|
9
|
+
|
|
10
|
+
bundle exec rails new ${test_app} \
|
|
11
|
+
--template=$(dirname "$0")/integration-template.rb \
|
|
12
|
+
--skip-bootsnap \
|
|
13
|
+
--skip-javascript \
|
|
14
|
+
--skip-spring \
|
|
15
|
+
--skip-turbolinks
|
|
16
|
+
|
|
17
|
+
cd ${test_app} && export BUNDLE_GEMFILE=Gemfile
|
|
18
|
+
|
|
19
|
+
bundle exec rake test
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'spec_helper'
|
|
3
4
|
require 'formtastic/action_class_finder'
|
|
4
5
|
|
|
5
|
-
describe Formtastic::ActionClassFinder do
|
|
6
|
+
RSpec.describe Formtastic::ActionClassFinder do
|
|
6
7
|
include FormtasticSpecHelper
|
|
7
8
|
|
|
8
9
|
it_behaves_like 'Specialized Class Finder' do
|
|
@@ -1,63 +1,64 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
require 'spec_helper'
|
|
3
4
|
|
|
4
|
-
describe 'ButtonAction', 'when submitting' do
|
|
5
|
+
RSpec.describe 'ButtonAction', 'when submitting' do
|
|
5
6
|
|
|
6
7
|
include FormtasticSpecHelper
|
|
7
8
|
|
|
8
9
|
before do
|
|
9
|
-
@output_buffer = ''
|
|
10
|
+
@output_buffer = ActionView::OutputBuffer.new ''
|
|
10
11
|
mock_everything
|
|
11
|
-
|
|
12
|
+
|
|
12
13
|
concat(semantic_form_for(@new_post) do |builder|
|
|
13
14
|
concat(builder.action(:submit, :as => :button))
|
|
14
15
|
end)
|
|
15
16
|
end
|
|
16
|
-
|
|
17
|
+
|
|
17
18
|
it 'should render a submit type of button' do
|
|
18
|
-
output_buffer.
|
|
19
|
+
expect(output_buffer.to_str).to have_tag('li.action.button_action button[@type="submit"]')
|
|
19
20
|
end
|
|
20
21
|
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
describe 'ButtonAction', 'when resetting' do
|
|
24
|
+
RSpec.describe 'ButtonAction', 'when resetting' do
|
|
24
25
|
|
|
25
26
|
include FormtasticSpecHelper
|
|
26
|
-
|
|
27
|
+
|
|
27
28
|
before do
|
|
28
|
-
@output_buffer = ''
|
|
29
|
+
@output_buffer = ActionView::OutputBuffer.new ''
|
|
29
30
|
mock_everything
|
|
30
|
-
|
|
31
|
+
|
|
31
32
|
concat(semantic_form_for(@new_post) do |builder|
|
|
32
33
|
concat(builder.action(:reset, :as => :button))
|
|
33
34
|
end)
|
|
34
35
|
end
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
it 'should render a reset type of button' do
|
|
37
|
-
output_buffer.
|
|
38
|
+
expect(output_buffer.to_str).to have_tag('li.action.button_action button[@type="reset"]', :text => "Reset Post")
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
it 'should not render a value attribute' do
|
|
41
|
-
output_buffer.
|
|
42
|
+
expect(output_buffer.to_str).not_to have_tag('li.action.button_action button[@value]')
|
|
42
43
|
end
|
|
43
|
-
|
|
44
|
+
|
|
44
45
|
end
|
|
45
46
|
|
|
46
|
-
describe 'InputAction', 'when cancelling' do
|
|
47
|
+
RSpec.describe 'InputAction', 'when cancelling' do
|
|
47
48
|
|
|
48
49
|
include FormtasticSpecHelper
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
before do
|
|
51
|
-
@output_buffer = ''
|
|
52
|
+
@output_buffer = ActionView::OutputBuffer.new ''
|
|
52
53
|
mock_everything
|
|
53
54
|
end
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
it 'should raise an error' do
|
|
56
|
-
|
|
57
|
+
expect {
|
|
57
58
|
concat(semantic_form_for(@new_post) do |builder|
|
|
58
59
|
concat(builder.action(:cancel, :as => :button))
|
|
59
60
|
end)
|
|
60
|
-
}.
|
|
61
|
+
}.to raise_error(Formtastic::UnsupportedMethodForAction)
|
|
61
62
|
end
|
|
62
|
-
|
|
63
|
+
|
|
63
64
|
end
|