structured_params 0.9.3 → 0.9.4

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: b571c05cd70b8d5f5d3cbf40de3d06158b8b1ddfa9d0a7bd1edb4a158cd05813
4
- data.tar.gz: 4eeb5375b4e0d1a80feb1c0185084858e2932591c61cef9fef5ee10a1acbad42
3
+ metadata.gz: 60e548d315d109b5010333626042b9b011e867ce533c38de971201e2c9d2d87a
4
+ data.tar.gz: d2606fcd8176f4dc916af2bf879b48545508032c4752343caf9db7f0789bb7c5
5
5
  SHA512:
6
- metadata.gz: fe8a1dee53c763112c935211fd941d746871cf28ef2a16499cabc71625e9a8219279fb354887d9d7f8bc80d13537cd123eb19a29feb6424351ffa720207b36b0
7
- data.tar.gz: b03d0e6cd37482e1ddc578788e3d46e191a73a53e5e091a34ee80ccf88bd1258aa2f29f3b5544fa9252309042f6060c9f630ab820087f29b29d9a7d786dca1fa
6
+ metadata.gz: e9c3970818c47a021c522d12ca409b56730d580961fb79dc6cc311da9756bdec5b971fcc4e7cc9d8a2dd611b363aa5977356e074fdf1f7bc162bfddc04287692
7
+ data.tar.gz: a7930657984c4554dc7b172a7d9982a6c40cfe128053efbd4afaae2a41e8839211e063b6be3b1b5022390bf70825251633c3feaf7e955363329a8f32b1e6722d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.4] - 2026-05-02
4
+
5
+ ## What's Changed
6
+ * Enhance array index handling and update RBS configuration by @Syati in https://github.com/Syati/structured_params/pull/16
7
+
8
+
9
+ **Full Changelog**: https://github.com/Syati/structured_params/compare/v0.9.3...v0.9.4
10
+
3
11
  ## [0.9.3] - 2026-04-09
4
12
 
5
13
  ## What's Changed
@@ -22,9 +22,12 @@ module StructuredParams
22
22
  # array: "%{parent} %{index} 番目の%{child}"
23
23
  # object: "%{parent}の%{child}"
24
24
  #
25
- # Without these keys the defaults are:
25
+ # Without these keys the defaults are (with array_index_base: 0):
26
26
  # array → "<parent> <index> <child>" (e.g. "Hobbies 0 Name")
27
27
  # object → "<parent> <child>" (e.g. "Address Postal code")
28
+ #
29
+ # With array_index_base: 1 (human-friendly):
30
+ # array → "Hobbies 1 Name"
28
31
  module I18n
29
32
  extend ActiveSupport::Concern
30
33
 
@@ -34,11 +37,11 @@ module StructuredParams
34
37
  # Flat attributes (no dot) are delegated to the default ActiveModel
35
38
  # behaviour unchanged.
36
39
  #
37
- # Example (en default):
40
+ # Example (en default, array_index_base: 0):
38
41
  # human_attribute_name(:'hobbies.0.name') # => "Hobbies 0 Name"
39
42
  #
40
- # Example with i18n (ja):
41
- # human_attribute_name(:'hobbies.0.name') # => "趣味 0 番目の名前"
43
+ # Example with i18n (ja) and array_index_base: 1:
44
+ # human_attribute_name(:'hobbies.0.name') # => "趣味 1 番目の名前"
42
45
  #
43
46
  #: (Symbol | String, ?Hash[untyped, untyped]) -> String
44
47
  def human_attribute_name(attribute, options = {})
@@ -99,6 +102,11 @@ module StructuredParams
99
102
  # activemodel.errors.nested_attribute.array (parent, index, child)
100
103
  # activemodel.errors.nested_attribute.object (parent, child)
101
104
  #
105
+ # The index value passed to the i18n template is adjusted by
106
+ # +StructuredParams.configuration.array_index_base+:
107
+ # * +0+ (default) – raw 0-based Ruby index (e.g. 0, 1, 2, …)
108
+ # * +1+ – human-friendly 1-based index (e.g. 1, 2, 3, …)
109
+ #
102
110
  # The +locale:+ key from +options+ is forwarded to ::I18n.t so that an
103
111
  # explicit locale passed to human_attribute_name is honoured.
104
112
  #
@@ -109,12 +117,13 @@ module StructuredParams
109
117
  i18n_opts = options.slice(:locale)
110
118
 
111
119
  if index
120
+ display_index = index.to_i + StructuredParams.configuration.array_index_base
112
121
  ::I18n.t(
113
122
  'activemodel.errors.nested_attribute.array',
114
123
  parent: result,
115
- index: index,
124
+ index: display_index,
116
125
  child: attr_human,
117
- default: "#{result} #{index} #{attr_human}",
126
+ default: "#{result} #{display_index} #{attr_human}",
118
127
  **i18n_opts
119
128
  )
120
129
  else
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module StructuredParams
5
- VERSION = '0.9.3' #: string
5
+ VERSION = '0.9.4' #: string
6
6
  end
@@ -23,17 +23,75 @@ require_relative 'structured_params/params'
23
23
 
24
24
  # Main module
25
25
  module StructuredParams
26
- # Helper method to register types
27
- #: () -> void
28
- def self.register_types
29
- ActiveModel::Type.register(:object, StructuredParams::Type::Object)
30
- ActiveModel::Type.register(:array, StructuredParams::Type::Array)
26
+ # Global configuration for StructuredParams.
27
+ #
28
+ # == Options
29
+ #
30
+ # +array_index_base+ (Integer, default: +0+)::
31
+ # Controls how array indices are displayed in human attribute names and
32
+ # error messages.
33
+ #
34
+ # * +0+ – 0-based (raw Ruby index): "Hobbies 0 Name"
35
+ # * +1+ – 1-based (human-friendly): "Hobbies 1 Name"
36
+ #
37
+ # This setting applies to both API param error messages and Form Object
38
+ # +full_messages+.
39
+ #
40
+ # == Example
41
+ #
42
+ # # config/initializers/structured_params.rb
43
+ # StructuredParams.configure do |config|
44
+ # config.array_index_base = 1 # show "1st" instead of "0th" to users
45
+ # end
46
+ #
47
+ class Configuration
48
+ attr_reader :array_index_base #: Integer
49
+
50
+ #: () -> void
51
+ def initialize
52
+ @array_index_base = 0
53
+ end
54
+
55
+ #: (Integer) -> void
56
+ def array_index_base=(value)
57
+ unless value.is_a?(Integer) && [0, 1].include?(value)
58
+ raise ArgumentError, "array_index_base must be 0 or 1, got: #{value.inspect}"
59
+ end
60
+
61
+ @array_index_base = value
62
+ end
31
63
  end
32
64
 
33
- # Helper method to register types with custom names
34
- #: (object_name: Symbol, array_name: Symbol) -> void
35
- def self.register_types_as(object_name:, array_name:)
36
- ActiveModel::Type.register(object_name, StructuredParams::Type::Object)
37
- ActiveModel::Type.register(array_name, StructuredParams::Type::Array)
65
+ class << self
66
+ # @rbs self.@configuration: Configuration?
67
+
68
+ #: () -> Configuration
69
+ def configuration
70
+ @configuration ||= Configuration.new
71
+ end
72
+
73
+ #: () { (Configuration) -> void } -> void
74
+ def configure
75
+ yield configuration
76
+ end
77
+
78
+ #: () -> void
79
+ def reset_configuration!
80
+ @configuration = Configuration.new
81
+ end
82
+
83
+ # Helper method to register types
84
+ #: () -> void
85
+ def register_types
86
+ ActiveModel::Type.register(:object, StructuredParams::Type::Object)
87
+ ActiveModel::Type.register(:array, StructuredParams::Type::Array)
88
+ end
89
+
90
+ # Helper method to register types with custom names
91
+ #: (object_name: Symbol, array_name: Symbol) -> void
92
+ def register_types_as(object_name:, array_name:)
93
+ ActiveModel::Type.register(object_name, StructuredParams::Type::Object)
94
+ ActiveModel::Type.register(array_name, StructuredParams::Type::Array)
95
+ end
38
96
  end
39
97
  end
@@ -21,9 +21,12 @@ module StructuredParams
21
21
  # array: "%{parent} %{index} 番目の%{child}"
22
22
  # object: "%{parent}の%{child}"
23
23
  #
24
- # Without these keys the defaults are:
24
+ # Without these keys the defaults are (with array_index_base: 0):
25
25
  # array → "<parent> <index> <child>" (e.g. "Hobbies 0 Name")
26
26
  # object → "<parent> <child>" (e.g. "Address Postal code")
27
+ #
28
+ # With array_index_base: 1 (human-friendly):
29
+ # array → "Hobbies 1 Name"
27
30
  module I18n
28
31
  extend ActiveSupport::Concern
29
32
 
@@ -32,11 +35,11 @@ module StructuredParams
32
35
  # Flat attributes (no dot) are delegated to the default ActiveModel
33
36
  # behaviour unchanged.
34
37
  #
35
- # Example (en default):
38
+ # Example (en default, array_index_base: 0):
36
39
  # human_attribute_name(:'hobbies.0.name') # => "Hobbies 0 Name"
37
40
  #
38
- # Example with i18n (ja):
39
- # human_attribute_name(:'hobbies.0.name') # => "趣味 0 番目の名前"
41
+ # Example with i18n (ja) and array_index_base: 1:
42
+ # human_attribute_name(:'hobbies.0.name') # => "趣味 1 番目の名前"
40
43
  #
41
44
  # : (Symbol | String, ?Hash[untyped, untyped]) -> String
42
45
  def human_attribute_name: (Symbol | String, ?Hash[untyped, untyped]) -> String
@@ -69,6 +72,11 @@ module StructuredParams
69
72
  # activemodel.errors.nested_attribute.array (parent, index, child)
70
73
  # activemodel.errors.nested_attribute.object (parent, child)
71
74
  #
75
+ # The index value passed to the i18n template is adjusted by
76
+ # +StructuredParams.configuration.array_index_base+:
77
+ # * +0+ (default) – raw 0-based Ruby index (e.g. 0, 1, 2, …)
78
+ # * +1+ – human-friendly 1-based index (e.g. 1, 2, 3, …)
79
+ #
72
80
  # The +locale:+ key from +options+ is forwarded to ::I18n.t so that an
73
81
  # explicit locale passed to human_attribute_name is honoured.
74
82
  #
@@ -29,6 +29,19 @@ module StructuredParams
29
29
  def serialize: (::Array[untyped]?) -> ::Array[untyped]?
30
30
 
31
31
  # Get permitted parameter names for use with Strong Parameters
32
+ #
33
+ # Returns:
34
+ # - For object arrays (value_class): nested keys from the object
35
+ # Example: HobbyParams with [:name, :level]
36
+ # → returns [:name, :level]
37
+ # → becomes { hobbies: [:name, :level] } in Params#permit_attribute_names
38
+ #
39
+ # - For primitive arrays (value_type): empty array
40
+ # Example: attribute :tags, :array, value_type: :string
41
+ # → returns []
42
+ # → becomes { tags: [] } in Params#permit_attribute_names
43
+ # → finally used as params.permit(:name, { tags: [] })
44
+ #
32
45
  # : () -> ::Array[untyped]
33
46
  def permit_attribute_names: () -> ::Array[untyped]
34
47
 
@@ -2,6 +2,47 @@
2
2
 
3
3
  # Main module
4
4
  module StructuredParams
5
+ # Global configuration for StructuredParams.
6
+ #
7
+ # == Options
8
+ #
9
+ # +array_index_base+ (Integer, default: +0+)::
10
+ # Controls how array indices are displayed in human attribute names and
11
+ # error messages.
12
+ #
13
+ # * +0+ – 0-based (raw Ruby index): "Hobbies 0 Name"
14
+ # * +1+ – 1-based (human-friendly): "Hobbies 1 Name"
15
+ #
16
+ # This setting applies to both API param error messages and Form Object
17
+ # +full_messages+.
18
+ #
19
+ # == Example
20
+ #
21
+ # # config/initializers/structured_params.rb
22
+ # StructuredParams.configure do |config|
23
+ # config.array_index_base = 1 # show "1st" instead of "0th" to users
24
+ # end
25
+ class Configuration
26
+ attr_reader array_index_base: Integer
27
+
28
+ # : () -> void
29
+ def initialize: () -> void
30
+
31
+ # : (Integer) -> void
32
+ def array_index_base=: (Integer) -> void
33
+ end
34
+
35
+ self.@configuration: Configuration?
36
+
37
+ # : () -> Configuration
38
+ def self.configuration: () -> Configuration
39
+
40
+ # : () { (Configuration) -> void } -> void
41
+ def self.configure: () { (Configuration) -> void } -> void
42
+
43
+ # : () -> void
44
+ def self.reset_configuration!: () -> void
45
+
5
46
  # Helper method to register types
6
47
  # : () -> void
7
48
  def self.register_types: () -> void
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: structured_params
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mizuki Yamamoto