phlexi-form 0.3.0.rc1 → 0.4.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -8
  3. data/gemfiles/default.gemfile.lock +34 -32
  4. data/gemfiles/rails_7.gemfile.lock +16 -18
  5. data/lib/phlexi/form/base.rb +42 -41
  6. data/lib/phlexi/form/builder.rb +297 -0
  7. data/lib/phlexi/form/components/base.rb +3 -3
  8. data/lib/phlexi/form/components/collection_checkboxes.rb +1 -1
  9. data/lib/phlexi/form/components/collection_radio_buttons.rb +1 -1
  10. data/lib/phlexi/form/components/concerns/extracts_input.rb +53 -0
  11. data/lib/phlexi/form/components/concerns/handles_input.rb +4 -34
  12. data/lib/phlexi/form/components/concerns/submits_form.rb +8 -0
  13. data/lib/phlexi/form/components/error.rb +1 -1
  14. data/lib/phlexi/form/components/file_input.rb +1 -0
  15. data/lib/phlexi/form/components/hint.rb +1 -1
  16. data/lib/phlexi/form/components/input.rb +16 -6
  17. data/lib/phlexi/form/components/input_array.rb +1 -1
  18. data/lib/phlexi/form/components/select.rb +4 -3
  19. data/lib/phlexi/form/components/textarea.rb +2 -3
  20. data/lib/phlexi/form/html.rb +18 -0
  21. data/lib/phlexi/form/{field_options → options}/autofocus.rb +1 -1
  22. data/lib/phlexi/form/{field_options → options}/collection.rb +14 -10
  23. data/lib/phlexi/form/{field_options → options}/disabled.rb +1 -1
  24. data/lib/phlexi/form/{field_options → options}/errors.rb +18 -14
  25. data/lib/phlexi/form/options/hints.rb +13 -0
  26. data/lib/phlexi/form/options/inferred_types.rb +32 -0
  27. data/lib/phlexi/form/{field_options → options}/length.rb +3 -3
  28. data/lib/phlexi/form/{field_options → options}/limit.rb +2 -2
  29. data/lib/phlexi/form/options/max.rb +55 -0
  30. data/lib/phlexi/form/options/min.rb +55 -0
  31. data/lib/phlexi/form/{field_options → options}/pattern.rb +2 -2
  32. data/lib/phlexi/form/{field_options → options}/readonly.rb +1 -1
  33. data/lib/phlexi/form/{field_options → options}/required.rb +3 -3
  34. data/lib/phlexi/form/options/step.rb +39 -0
  35. data/lib/phlexi/form/options/validators.rb +24 -0
  36. data/lib/phlexi/form/structure/field_collection.rb +12 -27
  37. data/lib/phlexi/form/structure/namespace.rb +4 -111
  38. data/lib/phlexi/form/structure/namespace_collection.rb +1 -32
  39. data/lib/phlexi/form/theme.rb +160 -0
  40. data/lib/phlexi/form/version.rb +1 -1
  41. data/lib/phlexi/form.rb +3 -6
  42. metadata +36 -24
  43. data/lib/phlexi/form/field_options/associations.rb +0 -21
  44. data/lib/phlexi/form/field_options/hints.rb +0 -22
  45. data/lib/phlexi/form/field_options/inferred_types.rb +0 -155
  46. data/lib/phlexi/form/field_options/labels.rb +0 -28
  47. data/lib/phlexi/form/field_options/min_max.rb +0 -92
  48. data/lib/phlexi/form/field_options/multiple.rb +0 -65
  49. data/lib/phlexi/form/field_options/placeholder.rb +0 -18
  50. data/lib/phlexi/form/field_options/themes.rb +0 -207
  51. data/lib/phlexi/form/field_options/validators.rb +0 -48
  52. data/lib/phlexi/form/structure/dom.rb +0 -62
  53. data/lib/phlexi/form/structure/field_builder.rb +0 -236
  54. data/lib/phlexi/form/structure/node.rb +0 -18
@@ -0,0 +1,160 @@
1
+ module Phlexi
2
+ module Form
3
+ class Theme < Phlexi::Field::Theme
4
+ def self.theme
5
+ @theme ||= {
6
+ # == Base
7
+ base: nil,
8
+ hint: nil,
9
+ error: nil,
10
+ full_error: :error,
11
+ wrapper: nil,
12
+ inner_wrapper: nil,
13
+ button: nil,
14
+ submit_button: :button,
15
+
16
+ # == Label
17
+ label: nil,
18
+ invalid_label: nil,
19
+ valid_label: nil,
20
+ neutral_label: nil,
21
+
22
+ # == Input
23
+ input: nil,
24
+ valid_input: nil,
25
+ invalid_input: nil,
26
+ neutral_input: nil,
27
+
28
+ # String
29
+ string: :input,
30
+ valid_string: :valid_input,
31
+ invalid_string: :invalid_input,
32
+ neutral_string: :neutral_input,
33
+
34
+ # Email
35
+ email: :input,
36
+ valid_email: :valid_input,
37
+ invalid_email: :invalid_input,
38
+ neutral_email: :neutral_input,
39
+
40
+ # Password
41
+ password: :input,
42
+ valid_password: :valid_input,
43
+ invalid_password: :invalid_input,
44
+ neutral_password: :neutral_input,
45
+
46
+ # Phone
47
+ phone: :input,
48
+ valid_phone: :valid_input,
49
+ invalid_phone: :invalid_input,
50
+ neutral_phone: :neutral_input,
51
+
52
+ # Color
53
+ color: :input,
54
+ valid_color: :valid_input,
55
+ invalid_color: :invalid_input,
56
+ neutral_color: :neutral_input,
57
+
58
+ # Url
59
+ url: :input,
60
+ valid_url: :valid_input,
61
+ invalid_url: :invalid_input,
62
+ neutral_url: :neutral_input,
63
+
64
+ # Search
65
+ search: :input,
66
+ valid_search: :valid_input,
67
+ invalid_search: :invalid_input,
68
+ neutral_search: :neutral_input,
69
+
70
+ # Number
71
+ number: :input,
72
+ valid_number: :valid_input,
73
+ invalid_number: :invalid_input,
74
+ neutral_number: :neutral_input,
75
+
76
+ # Date
77
+ date: :input,
78
+ valid_date: :valid_input,
79
+ invalid_date: :invalid_input,
80
+ neutral_date: :neutral_input,
81
+
82
+ # Time
83
+ time: :input,
84
+ valid_time: :valid_input,
85
+ invalid_time: :invalid_input,
86
+ neutral_time: :neutral_input,
87
+
88
+ # DateTime
89
+ datetime: :input,
90
+ valid_datetime: :valid_input,
91
+ invalid_datetime: :invalid_input,
92
+ neutral_datetime: :neutral_input,
93
+
94
+ # Checkbox
95
+ checkbox: :input,
96
+ valid_checkbox: :valid_input,
97
+ invalid_checkbox: :invalid_input,
98
+ neutral_checkbox: :neutral_input,
99
+
100
+ # Boolean
101
+ boolan: :checkbox,
102
+ valid_boolan: :valid_checkbox,
103
+ invalid_boolan: :invalid_checkbox,
104
+ neutral_boolan: :neutral_checkbox,
105
+
106
+ # Textarea
107
+ textarea: :input,
108
+ valid_textarea: :valid_input,
109
+ invalid_textarea: :invalid_input,
110
+ neutral_textarea: :neutral_input,
111
+
112
+ # Hstore
113
+ hstore: :textarea,
114
+ valid_hstore: :valid_textarea,
115
+ invalid_hstore: :invalid_textarea,
116
+ neutral_hstore: :neutral_textarea,
117
+
118
+ # Select
119
+ select: :input,
120
+ valid_select: :valid_input,
121
+ invalid_select: :invalid_input,
122
+ neutral_select: :neutral_input,
123
+
124
+ # File
125
+ file: :input,
126
+ valid_file: :valid_input,
127
+ invalid_file: :invalid_input,
128
+ neutral_file: :neutral_input
129
+
130
+ }.freeze
131
+ end
132
+
133
+ # Resolves the theme for a component based on its current validity state
134
+ #
135
+ # This method determines the validity state of the field (valid, invalid, or neutral)
136
+ # and returns the corresponding theme by prepending the state to the component name.
137
+ #
138
+ # @param property [Symbol, String] The base theme property to resolve
139
+ # @return [String, nil] The resolved validity-specific theme or nil if not found
140
+ #
141
+ # @example Resolving a validity theme
142
+ # # Assuming the field has errors and the theme includes { invalid_input: "error-class" }
143
+ # resolve_validity_theme(:input)
144
+ # # => "error-class"
145
+ def resolve_validity_theme(property, field)
146
+ return unless field
147
+
148
+ validity_property = if field.has_errors?
149
+ :"invalid_#{property}"
150
+ elsif field.object_valid?
151
+ :"valid_#{property}"
152
+ else
153
+ :"neutral_#{property}"
154
+ end
155
+
156
+ resolve_theme(validity_property)
157
+ end
158
+ end
159
+ end
160
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlexi
4
4
  module Form
5
- VERSION = "0.3.0.rc1"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
data/lib/phlexi/form.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "zeitwerk"
4
4
  require "phlex"
5
+ require "phlexi-field"
5
6
  require "active_support/core_ext/object/blank"
6
7
 
7
8
  module Phlexi
@@ -11,21 +12,17 @@ module Phlexi
11
12
  loader.inflector.inflect(
12
13
  "phlexi-form" => "Phlexi",
13
14
  "phlexi" => "Phlexi",
14
- "dom" => "DOM"
15
+ "html" => "HTML"
15
16
  )
16
17
  loader.push_dir(File.expand_path("..", __dir__))
17
18
  loader.ignore(File.expand_path("../generators", __dir__))
18
19
  loader.setup
19
20
  end
20
21
 
21
- COMPONENT_BASE = (defined?(::ApplicationComponent) ? ::ApplicationComponent : Phlex::HTML)
22
-
23
- NIL_VALUE = :__i_phlexi_form_nil_value_i__
24
-
25
22
  class Error < StandardError; end
26
23
  end
27
24
  end
28
25
 
29
26
  def Phlexi.Form(...)
30
- Phlexi::Form::Base.new(...)
27
+ Phlexi::Form::Base.inline(...)
31
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlexi-form
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.rc1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Froelich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-08 00:00:00.000000000 Z
11
+ date: 2024-09-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: phlexi-field
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: activesupport
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -190,10 +204,12 @@ files:
190
204
  - lib/phlexi-form.rb
191
205
  - lib/phlexi/form.rb
192
206
  - lib/phlexi/form/base.rb
207
+ - lib/phlexi/form/builder.rb
193
208
  - lib/phlexi/form/components/base.rb
194
209
  - lib/phlexi/form/components/checkbox.rb
195
210
  - lib/phlexi/form/components/collection_checkboxes.rb
196
211
  - lib/phlexi/form/components/collection_radio_buttons.rb
212
+ - lib/phlexi/form/components/concerns/extracts_input.rb
197
213
  - lib/phlexi/form/components/concerns/handles_array_input.rb
198
214
  - lib/phlexi/form/components/concerns/handles_input.rb
199
215
  - lib/phlexi/form/components/concerns/has_options.rb
@@ -210,31 +226,27 @@ files:
210
226
  - lib/phlexi/form/components/submit_button.rb
211
227
  - lib/phlexi/form/components/textarea.rb
212
228
  - lib/phlexi/form/components/wrapper.rb
213
- - lib/phlexi/form/field_options/associations.rb
214
- - lib/phlexi/form/field_options/autofocus.rb
215
- - lib/phlexi/form/field_options/collection.rb
216
- - lib/phlexi/form/field_options/disabled.rb
217
- - lib/phlexi/form/field_options/errors.rb
218
- - lib/phlexi/form/field_options/hints.rb
219
- - lib/phlexi/form/field_options/inferred_types.rb
220
- - lib/phlexi/form/field_options/labels.rb
221
- - lib/phlexi/form/field_options/length.rb
222
- - lib/phlexi/form/field_options/limit.rb
223
- - lib/phlexi/form/field_options/min_max.rb
224
- - lib/phlexi/form/field_options/multiple.rb
225
- - lib/phlexi/form/field_options/pattern.rb
226
- - lib/phlexi/form/field_options/placeholder.rb
227
- - lib/phlexi/form/field_options/readonly.rb
228
- - lib/phlexi/form/field_options/required.rb
229
- - lib/phlexi/form/field_options/themes.rb
230
- - lib/phlexi/form/field_options/validators.rb
229
+ - lib/phlexi/form/html.rb
231
230
  - lib/phlexi/form/option_mapper.rb
232
- - lib/phlexi/form/structure/dom.rb
233
- - lib/phlexi/form/structure/field_builder.rb
231
+ - lib/phlexi/form/options/autofocus.rb
232
+ - lib/phlexi/form/options/collection.rb
233
+ - lib/phlexi/form/options/disabled.rb
234
+ - lib/phlexi/form/options/errors.rb
235
+ - lib/phlexi/form/options/hints.rb
236
+ - lib/phlexi/form/options/inferred_types.rb
237
+ - lib/phlexi/form/options/length.rb
238
+ - lib/phlexi/form/options/limit.rb
239
+ - lib/phlexi/form/options/max.rb
240
+ - lib/phlexi/form/options/min.rb
241
+ - lib/phlexi/form/options/pattern.rb
242
+ - lib/phlexi/form/options/readonly.rb
243
+ - lib/phlexi/form/options/required.rb
244
+ - lib/phlexi/form/options/step.rb
245
+ - lib/phlexi/form/options/validators.rb
234
246
  - lib/phlexi/form/structure/field_collection.rb
235
247
  - lib/phlexi/form/structure/namespace.rb
236
248
  - lib/phlexi/form/structure/namespace_collection.rb
237
- - lib/phlexi/form/structure/node.rb
249
+ - lib/phlexi/form/theme.rb
238
250
  - lib/phlexi/form/version.rb
239
251
  - sig/phlexi/form.rbs
240
252
  homepage: https://github.com/radioactive-labs/phlexi-form
@@ -260,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
260
272
  - !ruby/object:Gem::Version
261
273
  version: '0'
262
274
  requirements: []
263
- rubygems_version: 3.5.11
275
+ rubygems_version: 3.4.10
264
276
  signing_key:
265
277
  specification_version: 4
266
278
  summary: Build forms in Rails
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Form
5
- module FieldOptions
6
- module Associations
7
- protected
8
-
9
- def reflection
10
- @reflection ||= find_association_reflection
11
- end
12
-
13
- def find_association_reflection
14
- if object.class.respond_to?(:reflect_on_association)
15
- object.class.reflect_on_association(key)
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Form
5
- module FieldOptions
6
- module Hints
7
- def hint(hint = nil)
8
- if hint.nil?
9
- options[:hint]
10
- else
11
- options[:hint] = hint
12
- self
13
- end
14
- end
15
-
16
- def has_hint?
17
- options[:hint] != false && hint.present?
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,155 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bigdecimal"
4
-
5
- module Phlexi
6
- module Form
7
- module FieldOptions
8
- module InferredTypes
9
- def inferred_db_type
10
- @inferred_db_type ||= infer_db_type
11
- end
12
-
13
- def inferred_input_component
14
- @inferred_input_component ||= infer_input_component
15
- end
16
-
17
- def inferred_input_type
18
- @inferred_input_type ||= infer_input_type(inferred_input_component)
19
- end
20
-
21
- private
22
-
23
- # this returns the element type
24
- # one of :input, :textarea, :select, :botton
25
- def infer_input_component
26
- return :select unless collection.blank?
27
-
28
- case inferred_db_type
29
- when :text, :json, :jsonb, :hstore
30
- :textarea
31
- else
32
- :input
33
- end
34
- end
35
-
36
- # this only applies when input_component is `:input`
37
- # resolves the type attribute of input components
38
- def infer_input_type(component)
39
- case inferred_db_type
40
- when :string
41
- infer_string_input_type(key)
42
- when :integer, :float, :decimal
43
- :number
44
- when :date
45
- :date
46
- when :datetime
47
- :datetime
48
- when :time
49
- :time
50
- when :boolean
51
- :checkbox
52
- else
53
- :text
54
- end
55
- end
56
-
57
- def infer_db_type
58
- if object.class.respond_to?(:columns_hash)
59
- # ActiveRecord object
60
- column = object.class.columns_hash[key.to_s]
61
- return column.type if column
62
- end
63
-
64
- if object.class.respond_to?(:attribute_types)
65
- # ActiveModel::Attributes
66
- custom_type = object.class.attribute_types[key.to_s]
67
- return custom_type.type if custom_type
68
- end
69
-
70
- # Check if object responds to the key
71
- if object.respond_to?(key)
72
- # Fallback to inferring type from the value
73
- return infer_db_type_from_value(object.send(key))
74
- end
75
-
76
- # Default to string if we can't determine the type
77
- :string
78
- end
79
-
80
- def infer_db_type_from_value(value)
81
- case value
82
- when Integer
83
- :integer
84
- when Float, BigDecimal
85
- :float
86
- when TrueClass, FalseClass
87
- :boolean
88
- when Date
89
- :date
90
- when Time, DateTime
91
- :datetime
92
- else
93
- :string
94
- end
95
- end
96
-
97
- def infer_string_input_type(key)
98
- key = key.to_s.downcase
99
-
100
- return :password if is_password_field?
101
-
102
- custom_type = custom_string_input_type(key)
103
- return custom_type if custom_type
104
-
105
- if has_validators?
106
- infer_string_input_type_from_validations
107
- else
108
- :text
109
- end
110
- end
111
-
112
- def custom_string_input_type(key)
113
- custom_mappings = {
114
- /url$|^link|^site/ => :url,
115
- /^email/ => :email,
116
- /^search/ => :search,
117
- /phone|tel(ephone)?/ => :tel,
118
- /^time/ => :time,
119
- /^date/ => :date,
120
- /^number|_count$|_amount$/ => :number,
121
- /^color/ => :color
122
- }
123
-
124
- custom_mappings.each do |pattern, type|
125
- return type if key.match?(pattern)
126
- end
127
-
128
- nil
129
- end
130
-
131
- def infer_string_input_type_from_validations
132
- if attribute_validators.find { |v| v.kind == :numericality }
133
- :number
134
- elsif attribute_validators.find { |v| v.kind == :format && v.options[:with] == URI::MailTo::EMAIL_REGEXP }
135
- :email
136
- else
137
- :text
138
- end
139
- end
140
-
141
- def is_password_field?
142
- key = self.key.to_s.downcase
143
-
144
- exact_matches = ["password"]
145
- prefixes = ["encrypted_"]
146
- suffixes = ["_password", "_digest", "_hash"]
147
-
148
- exact_matches.include?(key) ||
149
- prefixes.any? { |prefix| key.start_with?(prefix) } ||
150
- suffixes.any? { |suffix| key.end_with?(suffix) }
151
- end
152
- end
153
- end
154
- end
155
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Form
5
- module FieldOptions
6
- module Labels
7
- def label(label = nil)
8
- if label.nil?
9
- options[:label] = options.fetch(:label) { calculate_label }
10
- else
11
- options[:label] = label
12
- self
13
- end
14
- end
15
-
16
- private
17
-
18
- def calculate_label
19
- if object.class.respond_to?(:human_attribute_name)
20
- object.class.human_attribute_name(key.to_s, {base: object})
21
- else
22
- key.to_s.humanize
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Form
5
- module FieldOptions
6
- module MinMax
7
- def min(min_value = nil)
8
- if min_value.nil?
9
- options[:min] = options.fetch(:min) { calculate_min }
10
- else
11
- options[:min] = min_value
12
- self
13
- end
14
- end
15
-
16
- def max(max_value = nil)
17
- if max_value.nil?
18
- options[:max] = options.fetch(:max) { calculate_max }
19
- else
20
- options[:max] = max_value
21
- self
22
- end
23
- end
24
-
25
- def step
26
- 1 if min || max
27
- end
28
-
29
- private
30
-
31
- def calculate_min
32
- if (numericality_validator = find_numericality_validator)
33
- get_min_from_validator(numericality_validator)
34
- end
35
- end
36
-
37
- def calculate_max
38
- if (numericality_validator = find_numericality_validator)
39
- get_max_from_validator(numericality_validator)
40
- end
41
- end
42
-
43
- def find_numericality_validator
44
- find_validator(:numericality)
45
- end
46
-
47
- def get_min_from_validator(validator)
48
- options = validator.options
49
- min = if options.key?(:greater_than)
50
- {value: options[:greater_than], exclusive: true}
51
- elsif options.key?(:greater_than_or_equal_to)
52
- {value: options[:greater_than_or_equal_to], exclusive: false}
53
- end
54
- evaluate_and_adjust_min(min)
55
- end
56
-
57
- def get_max_from_validator(validator)
58
- options = validator.options
59
- max = if options.key?(:less_than)
60
- {value: options[:less_than], exclusive: true}
61
- elsif options.key?(:less_than_or_equal_to)
62
- {value: options[:less_than_or_equal_to], exclusive: false}
63
- end
64
- evaluate_and_adjust_max(max)
65
- end
66
-
67
- def evaluate_and_adjust_min(min)
68
- return nil unless min
69
-
70
- value = evaluate_numericality_validator_option(min[:value])
71
- min[:exclusive] ? value + 1 : value
72
- end
73
-
74
- def evaluate_and_adjust_max(max)
75
- return nil unless max
76
-
77
- value = evaluate_numericality_validator_option(max[:value])
78
- max[:exclusive] ? value - 1 : value
79
- end
80
-
81
- def evaluate_numericality_validator_option(option)
82
- case option
83
- when Proc
84
- option.arity.zero? ? option.call : option.call(object)
85
- else
86
- option
87
- end
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Phlexi
4
- module Form
5
- module FieldOptions
6
- module Multiple
7
- def multiple?
8
- options[:multiple] = options.fetch(:multiple) { calculate_multiple_field_value }
9
- end
10
-
11
- def multiple!(multiple = true)
12
- options[:multiple] = multiple
13
- self
14
- end
15
-
16
- private
17
-
18
- def calculate_multiple_field_value
19
- return true if reflection&.macro == :has_many
20
- return true if multiple_field_array_attribute?
21
-
22
- check_multiple_field_from_validators
23
- end
24
-
25
- def multiple_field_array_attribute?
26
- return false unless object.class.respond_to?(:columns_hash)
27
-
28
- column = object.class.columns_hash[key.to_s]
29
- return false unless column
30
-
31
- case object.class.connection.adapter_name.downcase
32
- when "postgresql"
33
- column.array? || (column.type == :string && column.sql_type.include?("[]"))
34
- end # || object.class.attribute_types[key.to_s].is_a?(ActiveRecord::Type::Serialized)
35
- rescue
36
- # Rails.logger.warn("Error checking multiple field array attribute: #{e.message}")
37
- false
38
- end
39
-
40
- def check_multiple_field_from_validators
41
- inclusion_validator = find_validator(:inclusion)
42
- length_validator = find_validator(:length)
43
-
44
- return false unless inclusion_validator || length_validator
45
-
46
- check_multiple_field_inclusion_validator(inclusion_validator) ||
47
- check_multiple_field_length_validator(length_validator)
48
- end
49
-
50
- def check_multiple_field_inclusion_validator(validator)
51
- return false unless validator
52
- in_option = validator.options[:in]
53
- return false unless in_option.is_a?(Array)
54
-
55
- validator.options[:multiple] == true || (multiple_field_array_attribute? && in_option.size > 1)
56
- end
57
-
58
- def check_multiple_field_length_validator(validator)
59
- return false unless validator
60
- validator.options[:maximum].to_i > 1 if validator.options[:maximum]
61
- end
62
- end
63
- end
64
- end
65
- end