structured_params 0.9.4 → 0.9.5

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: 60e548d315d109b5010333626042b9b011e867ce533c38de971201e2c9d2d87a
4
- data.tar.gz: d2606fcd8176f4dc916af2bf879b48545508032c4752343caf9db7f0789bb7c5
3
+ metadata.gz: 786740a05f9ea27ee5e8b4c5b05aec0c5807fbac8b5995911e94a35f385c4bf4
4
+ data.tar.gz: 13647825c70a9bdfa94f5dcc14a1ae4c6c175bfa75c14e4e89183d89ad422175
5
5
  SHA512:
6
- metadata.gz: e9c3970818c47a021c522d12ca409b56730d580961fb79dc6cc311da9756bdec5b971fcc4e7cc9d8a2dd611b363aa5977356e074fdf1f7bc162bfddc04287692
7
- data.tar.gz: a7930657984c4554dc7b172a7d9982a6c40cfe128053efbd4afaae2a41e8839211e063b6be3b1b5022390bf70825251633c3feaf7e955363329a8f32b1e6722d
6
+ metadata.gz: 0a4bb67dbe0b7429b07a94c926fc5a1975642992aaee50efdb58e8d9df6c9dd4cca8e7f19e35f2bd0a91c20a23c28940cf30eea27bcfcf062ed9f44b58d35ff6
7
+ data.tar.gz: 5b22220f7d90edf6b47ccadfe27aa0d1f5724388c7ca0976093dd9546936410539102c7336b9e74b7c224ed57816798b3fb5b8c6f2286da0bedc2511e3a367d6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.5] - 2026-07-12
4
+
5
+ ## What's Changed
6
+ * Refine README and installation copy by @Syati in https://github.com/Syati/structured_params/pull/18
7
+ * Simplify form object params initialization by @Syati in https://github.com/Syati/structured_params/pull/19
8
+
9
+
10
+ **Full Changelog**: https://github.com/Syati/structured_params/compare/v0.9.4...v0.9.5
11
+
3
12
  ## [0.9.4] - 2026-05-02
4
13
 
5
14
  ## What's Changed
@@ -37,7 +37,7 @@ module StructuredParams
37
37
  # end
38
38
  #
39
39
  # # In controller:
40
- # @form = UserRegistrationForm.new(UserRegistrationForm.permit(params))
40
+ # @form = UserRegistrationForm.new(params)
41
41
  # if @form.valid?
42
42
  # User.create!(@form.attributes)
43
43
  # redirect_to user_path
@@ -50,6 +50,7 @@ module StructuredParams
50
50
  # <%= f.text_field :name %>
51
51
  # <%= f.text_field :email %>
52
52
  # <% end %>
53
+ # rubocop:disable Metrics/ClassLength
53
54
  class Params
54
55
  include ActiveModel::Model
55
56
  include ActiveModel::Attributes
@@ -98,7 +99,7 @@ module StructuredParams
98
99
 
99
100
  # Permit parameters with optional require
100
101
  #
101
- # For Form Objects (with require):
102
+ # For Form Objects (explicit manual permit):
102
103
  # UserRegistrationForm.permit(params)
103
104
  # # equivalent to:
104
105
  # params.require(:user_registration).permit(*UserRegistrationForm.permit_attribute_names)
@@ -132,6 +133,11 @@ module StructuredParams
132
133
  end
133
134
  end
134
135
 
136
+ #: () -> bool
137
+ def form_class?
138
+ name&.end_with?('Form') || false
139
+ end
140
+
135
141
  private
136
142
 
137
143
  # Determine if the specified type is a StructuredParams type
@@ -156,27 +162,17 @@ module StructuredParams
156
162
  @errors ||= Errors.new(self)
157
163
  end
158
164
 
159
- # ========================================
160
- # Form object support methods
161
- # These methods enable integration with Rails form helpers (form_with, form_for)
162
- # ========================================
163
-
164
- # Indicates whether the form object has been persisted to database
165
- # Always returns false for parameter/form objects
165
+ # Form object support for Rails helpers.
166
166
  #: () -> bool
167
167
  def persisted?
168
168
  false
169
169
  end
170
170
 
171
- # Returns the primary key value for the model
172
- # Always returns nil for parameter/form objects
173
171
  #: () -> nil
174
172
  def to_key
175
173
  nil
176
174
  end
177
175
 
178
- # Returns self for form helpers
179
- # Required by Rails form helpers to get the model object
180
176
  #: () -> self
181
177
  def to_model
182
178
  self
@@ -212,7 +208,7 @@ module StructuredParams
212
208
  def process_input_parameters(params)
213
209
  case params
214
210
  when ActionController::Parameters
215
- self.class.permit(params, require: false).to_h
211
+ process_action_controller_parameters(params)
216
212
  when Hash
217
213
  # ActiveModel::Attributes can handle both symbol and string keys
218
214
  params
@@ -221,6 +217,58 @@ module StructuredParams
221
217
  end
222
218
  end
223
219
 
220
+ #: (ActionController::Parameters) -> Hash[untyped, untyped]
221
+ def process_action_controller_parameters(params)
222
+ self.class.permit(params, require: require_nested_parameters?(params)).to_h
223
+ end
224
+
225
+ # Whether to call params.require(param_key) before permitting.
226
+ #
227
+ # Only ever true for Form-suffixed classes (form_class?); non-Form
228
+ # Params/Parameters subclasses always permit the top level directly.
229
+ #
230
+ # - A value nested under the model's param_key (e.g. params[:user_registration])
231
+ # always wins, even if params were already permitted higher up, since that
232
+ # inner key still needs to be require()'d out.
233
+ # - Otherwise, params that are already permitted, or whose shape looks flat
234
+ # (see flat_parameters?), are used as-is without requiring.
235
+ # - Anything else falls through to true, so params.require raises
236
+ # ActionController::ParameterMissing instead of guessing which keys
237
+ # belong to this form.
238
+ #: (ActionController::Parameters) -> bool
239
+ def require_nested_parameters?(params)
240
+ return false unless self.class.form_class?
241
+ return true if matches_model_name?(params)
242
+ return false if params.permitted?
243
+ return false if flat_parameters?(params)
244
+
245
+ true
246
+ end
247
+
248
+ #: (ActionController::Parameters) -> bool
249
+ def matches_model_name?(params)
250
+ key = self.class.model_name.param_key
251
+ return false unless params.key?(key)
252
+
253
+ params[key].is_a?(ActionController::Parameters)
254
+ end
255
+
256
+ # Only treat params as already-flat attributes when none of the top-level
257
+ # values are themselves nested. A nested value under some other key means
258
+ # the request shape is ambiguous, so we fall through to raising
259
+ # ParameterMissing instead of silently guessing which keys belong here.
260
+ #: (ActionController::Parameters) -> bool
261
+ def flat_parameters?(params)
262
+ return false if params.values.any?(ActionController::Parameters)
263
+
264
+ attribute_keys_present?(params)
265
+ end
266
+
267
+ #: (ActionController::Parameters) -> bool
268
+ def attribute_keys_present?(params)
269
+ params.keys.any? { |key| self.class.attribute_types.key?(key.to_s) }
270
+ end
271
+
224
272
  # Execute structured parameter validation
225
273
  #: () -> void
226
274
  def validate_structured_parameters
@@ -299,4 +347,5 @@ module StructuredParams
299
347
  end
300
348
  end
301
349
  end
350
+ # rubocop:enable Metrics/ClassLength
302
351
  end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module StructuredParams
5
- VERSION = '0.9.4' #: string
5
+ VERSION = '0.9.5' #: string
6
6
  end
@@ -36,7 +36,7 @@ module StructuredParams
36
36
  # end
37
37
  #
38
38
  # # In controller:
39
- # @form = UserRegistrationForm.new(UserRegistrationForm.permit(params))
39
+ # @form = UserRegistrationForm.new(params)
40
40
  # if @form.valid?
41
41
  # User.create!(@form.attributes)
42
42
  # redirect_to user_path
@@ -49,6 +49,7 @@ module StructuredParams
49
49
  # <%= f.text_field :name %>
50
50
  # <%= f.text_field :email %>
51
51
  # <% end %>
52
+ # rubocop:disable Metrics/ClassLength
52
53
  class Params
53
54
  include ActiveModel::Model
54
55
 
@@ -84,7 +85,7 @@ module StructuredParams
84
85
 
85
86
  # Permit parameters with optional require
86
87
  #
87
- # For Form Objects (with require):
88
+ # For Form Objects (explicit manual permit):
88
89
  # UserRegistrationForm.permit(params)
89
90
  # # equivalent to:
90
91
  # params.require(:user_registration).permit(*UserRegistrationForm.permit_attribute_names)
@@ -101,6 +102,9 @@ module StructuredParams
101
102
  # : () -> Hash[Symbol, singleton(::StructuredParams::Params)]
102
103
  def self.structured_attributes: () -> Hash[Symbol, singleton(::StructuredParams::Params)]
103
104
 
105
+ # : () -> bool
106
+ def self.form_class?: () -> bool
107
+
104
108
  # Determine if the specified type is a StructuredParams type
105
109
  # : (ActiveModel::Type::Value) -> bool
106
110
  private def self.structured_params_type?: (ActiveModel::Type::Value) -> bool
@@ -111,18 +115,13 @@ module StructuredParams
111
115
  # : () -> ::StructuredParams::Errors
112
116
  def errors: () -> ::StructuredParams::Errors
113
117
 
114
- # Indicates whether the form object has been persisted to database
115
- # Always returns false for parameter/form objects
118
+ # Form object support for Rails helpers.
116
119
  # : () -> bool
117
120
  def persisted?: () -> bool
118
121
 
119
- # Returns the primary key value for the model
120
- # Always returns nil for parameter/form objects
121
122
  # : () -> nil
122
123
  def to_key: () -> nil
123
124
 
124
- # Returns self for form helpers
125
- # Required by Rails form helpers to get the model object
126
125
  # : () -> self
127
126
  def to_model: () -> self
128
127
 
@@ -138,6 +137,38 @@ module StructuredParams
138
137
  # : (untyped) -> Hash[untyped, untyped]
139
138
  def process_input_parameters: (untyped) -> Hash[untyped, untyped]
140
139
 
140
+ # : (ActionController::Parameters) -> Hash[untyped, untyped]
141
+ def process_action_controller_parameters: (ActionController::Parameters) -> Hash[untyped, untyped]
142
+
143
+ # Whether to call params.require(param_key) before permitting.
144
+ #
145
+ # Only ever true for Form-suffixed classes (form_class?); non-Form
146
+ # Params/Parameters subclasses always permit the top level directly.
147
+ #
148
+ # - A value nested under the model's param_key (e.g. params[:user_registration])
149
+ # always wins, even if params were already permitted higher up, since that
150
+ # inner key still needs to be require()'d out.
151
+ # - Otherwise, params that are already permitted, or whose shape looks flat
152
+ # (see flat_parameters?), are used as-is without requiring.
153
+ # - Anything else falls through to true, so params.require raises
154
+ # ActionController::ParameterMissing instead of guessing which keys
155
+ # belong to this form.
156
+ # : (ActionController::Parameters) -> bool
157
+ def require_nested_parameters?: (ActionController::Parameters) -> bool
158
+
159
+ # : (ActionController::Parameters) -> bool
160
+ def matches_model_name?: (ActionController::Parameters) -> bool
161
+
162
+ # Only treat params as already-flat attributes when none of the top-level
163
+ # values are themselves nested. A nested value under some other key means
164
+ # the request shape is ambiguous, so we fall through to raising
165
+ # ParameterMissing instead of silently guessing which keys belong here.
166
+ # : (ActionController::Parameters) -> bool
167
+ def flat_parameters?: (ActionController::Parameters) -> bool
168
+
169
+ # : (ActionController::Parameters) -> bool
170
+ def attribute_keys_present?: (ActionController::Parameters) -> bool
171
+
141
172
  # Execute structured parameter validation
142
173
  # : () -> void
143
174
  def validate_structured_parameters: () -> 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.4
4
+ version: 0.9.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mizuki Yamamoto
@@ -49,7 +49,9 @@ dependencies:
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
51
  version: '9.0'
52
- description: ''
52
+ description: StructuredParams provides typed parameter objects for Rails APIs and
53
+ forms, with nested object and array support, Strong Parameters integration, and
54
+ raw-input validation via validates_raw.
53
55
  email:
54
56
  - mizuki-y@syati.info
55
57
  executables: []
@@ -101,5 +103,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
103
  requirements: []
102
104
  rubygems_version: 3.6.9
103
105
  specification_version: 4
104
- summary: Type-safe parameter validation and form objects for Rails.
106
+ summary: Typed parameter objects and form objects for Rails.
105
107
  test_files: []