phlexi-form 0.7.1 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 694c2f691f7e7b48e3b5df89dc1bc16badcbf88d4cb3fe528f106385aa448d93
4
- data.tar.gz: e0f6d6c3a12b7db210030d3cebfa2223d117839484bf6da38351281b219c1f34
3
+ metadata.gz: 8747d53fec5851c3ad3f78d2c60fecfea530de3b033eb074ee5f4ce41bcd3181
4
+ data.tar.gz: 51c02f430a3a81a4ee05197463a14aa9b00804c0a5b3a1837f36533b006d9860
5
5
  SHA512:
6
- metadata.gz: a269b67fc4679879244626a6734730f8b941a8fb1107837ecf057bb0d43c7003fe845f9614eb3f005a9cd594d2c2d048056f6aaf4858cb2be226c3b49d2cfb07
7
- data.tar.gz: a1b5899de6524100d3996d2594b0d544626c3e04df4c7c85f07b365864be73c0a957a10d5ac38d625d3622f47dbd20bd0bc2c826aa90904e8538fe1bff2a54fb
6
+ metadata.gz: 7434f1529fda38b7e02318c01be2fba09a97de755c874d2319730e4118d747a20bac457e7421bb34f0280f7e405079717df55e3d5ba3f32934f51deb1ebf43d7
7
+ data.tar.gz: 7457a359784b5404fee4a86ecdce99769f7899e080b7148aaff045719d536499efb4c6103c04334675258af94b74dbd10a9acacb7f327fb3a0f5f1508223f5bd
@@ -9,27 +9,57 @@ module Phlexi
9
9
 
10
10
  def build_attributes
11
11
  super
12
- @choice_collection = attributes.delete(:choices) || field.choices
13
12
  @label_method = attributes.delete(:label_method)
14
13
  @value_method = attributes.delete(:value_method)
14
+ @group_method = attributes.delete(:group_method)
15
+ @group_label_method = attributes.delete(:group_label_method)
15
16
  end
16
17
 
17
18
  def choices
18
- @choices ||= ChoicesMapper.new(@choice_collection, label_method: @label_method, value_method: @value_method)
19
+ @choices ||= begin
20
+ collection = attributes.delete(:choices) || field.choices
21
+ build_choice_mapper(collection)
22
+ end
19
23
  end
20
24
 
21
25
  def selected?(option)
22
26
  if attributes[:multiple]
23
- @options_list ||= Array(field.value)
24
- @options_list.any? { |item| item.to_s == option.to_s }
27
+ field_value.any? { |item| item.to_s == option.to_s }
28
+ else
29
+ field_value.to_s == option.to_s
30
+ end
31
+ end
32
+
33
+ def field_value
34
+ if attributes[:multiple]
35
+ Array(field.value)
25
36
  else
26
- field.value.to_s == option.to_s
37
+ field.value
27
38
  end
28
39
  end
29
40
 
30
41
  def normalize_simple_input(input_value)
42
+ # ensure that choice is in the list
31
43
  ([super] & choices.values)[0]
32
44
  end
45
+
46
+ def build_choice_mapper(collection)
47
+ if @group_method
48
+ GroupedChoicesMapper.new(
49
+ collection,
50
+ group_method: @group_method,
51
+ group_label_method: @group_label_method,
52
+ label_method: @label_method,
53
+ value_method: @value_method
54
+ )
55
+ else
56
+ SimpleChoicesMapper.new(
57
+ collection,
58
+ label_method: @label_method,
59
+ value_method: @value_method
60
+ )
61
+ end
62
+ end
33
63
  end
34
64
  end
35
65
  end
@@ -16,6 +16,8 @@ module Phlexi
16
16
  def build_input_attributes
17
17
  attributes[:type] = :file
18
18
  super
19
+
20
+ @include_hidden = attributes.delete(:include_hidden)
19
21
  # ensure we are always setting it to false
20
22
  attributes[:value] = false
21
23
  end
@@ -19,8 +19,18 @@ module Phlexi
19
19
  protected
20
20
 
21
21
  def options
22
- choices.each do |value, label|
23
- option(selected: selected?(value), value: value) { label }
22
+ if choices.is_a?(GroupedChoicesMapper)
23
+ choices.each do |group_label, group_choices|
24
+ optgroup(label: group_label) do
25
+ group_choices.each do |value, label|
26
+ option(selected: selected?(value), value: value) { label }
27
+ end
28
+ end
29
+ end
30
+ else
31
+ choices.each do |value, label|
32
+ option(selected: selected?(value), value: value) { label }
33
+ end
24
34
  end
25
35
  end
26
36
 
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phlexi
4
+ module Form
5
+ class GroupedChoicesMapper
6
+ include Enumerable
7
+
8
+ def initialize(collection, group_method:, group_label_method: :to_s, label_method: nil, value_method: nil)
9
+ @collection = collection
10
+ @group_method = group_method
11
+ @group_label_method = group_label_method
12
+ @label_method = label_method
13
+ @value_method = value_method
14
+ end
15
+
16
+ def each(&)
17
+ grouped_choices.each(&)
18
+ end
19
+
20
+ def grouped_choices
21
+ @grouped_choices ||= materialize_grouped_choices(@collection)
22
+ end
23
+
24
+ def materialize_grouped_choices(collection)
25
+ case collection
26
+ in Hash => hash
27
+ hash.transform_values { |items| to_choices_mapper(items) }
28
+ in Array => arr
29
+ array_to_grouped_hash(arr)
30
+ in Proc => proc
31
+ materialize_grouped_choices(proc.call)
32
+ else
33
+ record_collection_to_hash
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def array_to_grouped_hash(array)
40
+ sample = array.first
41
+ if group_method == :last && sample.is_a?(Array) && sample.size == 2
42
+ array.each_with_object({}) do |(label, items), hash|
43
+ hash[label.to_s] = to_choices_mapper(items)
44
+ end
45
+ else
46
+ record_collection_to_hash
47
+ end
48
+ end
49
+
50
+ def record_collection_to_hash
51
+ @collection.group_by do |item|
52
+ group = item.public_send(@group_method)
53
+ group.public_send(@group_label_method).to_s
54
+ end.transform_values { |items| to_choices_mapper(items) }
55
+ end
56
+
57
+ def to_choices_mapper(items)
58
+ SimpleChoicesMapper.new(items, label_method: @label_method, value_method: @value_method)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -2,31 +2,31 @@
2
2
 
3
3
  module Phlexi
4
4
  module Form
5
- # ChoicesMapper is responsible for converting a collection of objects into a hash of options
5
+ # SimpleChoicesMapper is responsible for converting a collection of objects into a hash of options
6
6
  # suitable for form controls, such as `select > options`.
7
7
  # Both values and labels are converted to strings.
8
8
  #
9
9
  # @example Basic usage
10
10
  # collection = [["First", 1], ["Second", 2]]
11
- # mapper = ChoicesMapper.new(collection)
11
+ # mapper = SimpleChoicesMapper.new(collection)
12
12
  # mapper.each { |value, label| puts "#{value}: #{label}" }
13
13
  #
14
14
  # @example Using with ActiveRecord objects
15
15
  # users = User.all
16
- # mapper = ChoicesMapper.new(users)
16
+ # mapper = SimpleChoicesMapper.new(users)
17
17
  # mapper.each { |id, name| puts "#{id}: #{name}" }
18
18
  #
19
19
  # @example Array access with different value types
20
- # mapper = ChoicesMapper.new([["Integer", 1], ["String", "2"], ["Symbol", :three]])
20
+ # mapper = SimpleChoicesMapper.new([["Integer", 1], ["String", "2"], ["Symbol", :three]])
21
21
  # puts mapper["1"] # Output: "Integer"
22
22
  # puts mapper["2"] # Output: "String"
23
23
  # puts mapper["three"] # Output: "Symbol"
24
24
  #
25
25
  # @note This class is thread-safe as it doesn't maintain mutable state.
26
- class ChoicesMapper
26
+ class SimpleChoicesMapper
27
27
  include Enumerable
28
28
 
29
- # Initializes a new ChoicesMapper instance.
29
+ # Initializes a new SimpleChoicesMapper instance.
30
30
  #
31
31
  # @param collection [#call, #to_a] The collection to be mapped.
32
32
  # @param label_method [Symbol, nil] The method to call on each object to get the label.
@@ -93,9 +93,9 @@ module Phlexi
93
93
  else
94
94
  array_to_hash(Array(collection))
95
95
  end
96
- rescue ArgumentError
97
- # Rails.logger.warn("Unhandled inclusion collection type: #{e}")TODO
98
- {}
96
+ # rescue ArgumentError
97
+ # # Rails.logger.warn("Unhandled inclusion collection type: #{e}")TODO
98
+ # {}
99
99
  end
100
100
 
101
101
  # Converts an array to a hash using detected or specified methods.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Phlexi
4
4
  module Form
5
- VERSION = "0.7.1"
5
+ VERSION = "0.8.0"
6
6
  end
7
7
  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.7.1
4
+ version: 0.8.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-12-29 00:00:00.000000000 Z
11
+ date: 2025-01-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: phlex
@@ -205,7 +205,6 @@ files:
205
205
  - lib/phlexi/form.rb
206
206
  - lib/phlexi/form/base.rb
207
207
  - lib/phlexi/form/builder.rb
208
- - lib/phlexi/form/choices_mapper.rb
209
208
  - lib/phlexi/form/components/base.rb
210
209
  - lib/phlexi/form/components/belongs_to.rb
211
210
  - lib/phlexi/form/components/checkbox.rb
@@ -231,6 +230,7 @@ files:
231
230
  - lib/phlexi/form/components/submit_button.rb
232
231
  - lib/phlexi/form/components/textarea.rb
233
232
  - lib/phlexi/form/components/wrapper.rb
233
+ - lib/phlexi/form/grouped_choices_mapper.rb
234
234
  - lib/phlexi/form/html.rb
235
235
  - lib/phlexi/form/options/autofocus.rb
236
236
  - lib/phlexi/form/options/choices.rb
@@ -247,6 +247,7 @@ files:
247
247
  - lib/phlexi/form/options/required.rb
248
248
  - lib/phlexi/form/options/step.rb
249
249
  - lib/phlexi/form/options/validators.rb
250
+ - lib/phlexi/form/simple_choices_mapper.rb
250
251
  - lib/phlexi/form/structure/field_collection.rb
251
252
  - lib/phlexi/form/structure/manages_fields.rb
252
253
  - lib/phlexi/form/structure/namespace.rb