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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/structured_params/i18n.rb +15 -6
- data/lib/structured_params/version.rb +1 -1
- data/lib/structured_params.rb +68 -10
- data/sig/structured_params/i18n.rbs +12 -4
- data/sig/structured_params/type/array.rbs +13 -0
- data/sig/structured_params.rbs +41 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 60e548d315d109b5010333626042b9b011e867ce533c38de971201e2c9d2d87a
|
|
4
|
+
data.tar.gz: d2606fcd8176f4dc916af2bf879b48545508032c4752343caf9db7f0789bb7c5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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') # => "趣味
|
|
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:
|
|
124
|
+
index: display_index,
|
|
116
125
|
child: attr_human,
|
|
117
|
-
default: "#{result} #{
|
|
126
|
+
default: "#{result} #{display_index} #{attr_human}",
|
|
118
127
|
**i18n_opts
|
|
119
128
|
)
|
|
120
129
|
else
|
data/lib/structured_params.rb
CHANGED
|
@@ -23,17 +23,75 @@ require_relative 'structured_params/params'
|
|
|
23
23
|
|
|
24
24
|
# Main module
|
|
25
25
|
module StructuredParams
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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') # => "趣味
|
|
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
|
|
data/sig/structured_params.rbs
CHANGED
|
@@ -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
|