@@ -11,238 +11,83 @@ English | [日本語](README_ja.md)
1111- ** Array handling** for both primitive types and nested objects
1212- ** Strong Parameters integration** with automatic permit lists
1313- ** ActiveModel compatibility** with validations and serialization
14+ - ** Enhanced error handling** with flat and structured formats
1415- ** RBS type definitions** for better development experience
1516
16- ## Installation
17-
18- Add this line to your application's Gemfile:
17+ ## Quick Start
1918
2019``` ruby
20+ # 1. Install the gem
2121gem ' structured_params'
22- ```
23-
24- And then execute:
25-
26- ``` bash
27- $ bundle install
28- ```
29-
30- Or install it yourself as:
31-
32- ``` bash
33- $ gem install structured_params
34- ```
35-
36- ## Setup
3722
38- Register the custom types in your Rails application:
39-
40- ``` ruby
41- # config/initializers/structured_params.rb
23+ # 2. Register types in initializer
4224StructuredParams .register_types
43- ```
44-
45- This registers ` :object ` and ` :array ` types with ActiveModel::Type.
46-
47- ## Usage
4825
49- ### Basic Parameter Class
50-
51- ``` ruby
26+ # 3. Define parameter classes
5227class UserParams < StructuredParams ::Params
5328 attribute :name , :string
5429 attribute :age , :integer
55- attribute :email , :string
30+ attribute :address , :object , value_class: AddressParams
31+ attribute :hobbies , :array , value_class: HobbyParams
5632
5733 validates :name , presence: true
58- validates :email , format : { with: URI :: MailTo :: EMAIL_REGEXP }
34+ validates :age , numericality : { greater_than: 0 }
5935end
6036
61- # Usage in controller
37+ # 4. Use in controllers
6238def create
6339 user_params = UserParams .new (params[:user ])
6440 if user_params.valid?
6541 User .create!(user_params.attributes)
6642 else
67- render json: { errors: user_params.errors }
43+ render json: { errors: user_params.errors.to_hash( false , structured: true ) }
6844 end
6945end
7046```
7147
72- ### Nested Objects
48+ ## Documentation
49+
50+ - ** [ Installation and Setup] ( docs/installation.md ) ** - Getting started with StructuredParams
51+ - ** [ Basic Usage] ( docs/basic-usage.md ) ** - Parameter classes, nested objects, and arrays
52+ - ** [ Validation] ( docs/validation.md ) ** - Using ActiveModel validations with nested structures
53+ - ** [ Strong Parameters] ( docs/strong-parameters.md ) ** - Automatic permit list generation
54+ - ** [ Error Handling] ( docs/error-handling.md ) ** - Flat and structured error formats
55+ - ** [ Serialization] ( docs/serialization.md ) ** - Converting parameters to hashes and JSON
56+ - ** [ Advanced Usage] ( docs/advanced-usage.md ) ** - Type introspection, performance tips, and more
57+
58+ ## Example
7359
7460``` ruby
7561class AddressParams < StructuredParams ::Params
7662 attribute :street , :string
7763 attribute :city , :string
7864 attribute :postal_code , :string
65+
66+ validates :street , :city , :postal_code , presence: true
7967end
8068
8169class UserParams < StructuredParams ::Params
8270 attribute :name , :string
71+ attribute :email , :string
8372 attribute :address , :object , value_class: AddressParams
73+
74+ validates :name , presence: true
75+ validates :email , format: { with: URI ::MailTo ::EMAIL_REGEXP }
8476end
8577
8678# Usage
8779params = {
8880 name: " John Doe" ,
89- address: {
90- street: " 123 Main St" ,
91- city: " New York" ,
92- postal_code: " 10001"
93- }
81+ email: " john@example.com" ,
82+ address: { street: " 123 Main St" , city: " New York" , postal_code: " 10001" }
9483}
9584
9685user_params = UserParams .new (params)
97- user_params.address # => AddressParams instance
86+ user_params.valid? # => true
9887user_params.address.city # => "New York"
88+ user_params.attributes # => Hash ready for ActiveRecord
9989```
10090
101- ### Arrays
102-
103- #### Array of Primitive Types
104-
105- ``` ruby
106- class UserParams < StructuredParams ::Params
107- attribute :tags , :array , value_type: :string
108- attribute :scores , :array , value_type: :integer
109- end
110-
111- # Usage
112- params = {
113- tags: [" ruby" , " rails" , " programming" ],
114- scores: [85 , 92 , 78 ]
115- }
116-
117- user_params = UserParams .new (params)
118- user_params.tags # => ["ruby", "rails", "programming"]
119- user_params.scores # => [85, 92, 78]
120- ```
121-
122- #### Array of Nested Objects
123-
124- ``` ruby
125- class HobbyParams < StructuredParams ::Params
126- attribute :name , :string
127- attribute :level , :string
128- end
129-
130- class UserParams < StructuredParams ::Params
131- attribute :name , :string
132- attribute :hobbies , :array , value_class: HobbyParams
133- end
134-
135- # Usage
136- params = {
137- name: " Alice" ,
138- hobbies: [
139- { name: " Photography" , level: " beginner" },
140- { name: " Cooking" , level: " intermediate" }
141- ]
142- }
143-
144- user_params = UserParams .new (params)
145- user_params.hobbies # => [HobbyParams, HobbyParams]
146- user_params.hobbies.first.name # => "Photography"
147- ```
148-
149- ### Strong Parameters Integration
150-
151- StructuredParams automatically generates permit lists for Strong Parameters:
152-
153- ``` ruby
154- class UsersController < ApplicationController
155- def create
156- permitted_params = params.require(:user ).permit(* UserParams .permit_attribute_names)
157- user_params = UserParams .new (permitted_params)
158-
159- if user_params.valid?
160- User .create!(user_params.attributes)
161- else
162- render json: { errors: user_params.errors }
163- end
164- end
165- end
166-
167- # UserParams.permit_attribute_names returns:
168- # [:name, :age, :email, { address: [:street, :city, :postal_code] }, { hobbies: [:name, :level] }]
169- ```
170-
171- ### Validation
172-
173- Since StructuredParams inherits from ActiveModel, you can use all ActiveModel validations:
174-
175- ``` ruby
176- class UserParams < StructuredParams ::Params
177- attribute :name , :string
178- attribute :age , :integer
179- attribute :email , :string
180- attribute :address , :object , value_class: AddressParams
181-
182- validates :name , presence: true , length: { minimum: 2 }
183- validates :age , presence: true , numericality: { greater_than: 0 }
184- validates :email , presence: true , format: { with: URI ::MailTo ::EMAIL_REGEXP }
185- validates :address , presence: true
186-
187- validate :custom_validation
188-
189- private
190-
191- def custom_validation
192- errors.add(:age , " must be adult" ) if age && age < 18
193- end
194- end
195- ```
196-
197- ### Serialization
198-
199- ``` ruby
200- user_params = UserParams .new (params)
201- user_params.attributes # => Hash with all attributes
202- user_params.to_json # => JSON string
203- ```
204-
205- ## Advanced Usage
206-
207- ### Custom Type Registration
208-
209- If you want to avoid potential naming conflicts, you can register types with custom names:
210-
211- ``` ruby
212- # Register with custom names
213- StructuredParams .register_types_as(
214- object_name: :structured_object ,
215- array_name: :structured_array
216- )
217-
218- # Then use in your parameter classes
219- class UserParams < StructuredParams ::Params
220- attribute :address , :structured_object , value_class: AddressParams
221- attribute :hobbies , :structured_array , value_class: HobbyParams
222- end
223- ```
224-
225- ### Type Introspection
226-
227- ``` ruby
228- user_params = UserParams .new (params)
229-
230- # Check attribute types
231- UserParams .attribute_types[:name ].type # => :string
232- UserParams .attribute_types[:address ].type # => :object
233- UserParams .attribute_types[:hobbies ].type # => :array
234-
235- # Access nested value classes
236- UserParams .attribute_types[:address ].value_class # => AddressParams
237- UserParams .attribute_types[:hobbies ].value_class # => HobbyParams
238- ```
239-
240- ## Development
241-
242- After checking out the repo, run ` bin/setup ` to install dependencies. Then, run ` rake spec ` to run the tests. You can also run ` bin/console ` for an interactive prompt that will allow you to experiment.
243-
244- To install this gem onto your local machine, run ` bundle exec rake install ` . To release a new version, update the version number in ` version.rb ` , and then run ` bundle exec rake release ` , which will create a git tag for the version, push git commits and the created tag, and push the ` .gem ` file to [ rubygems.org] ( https://rubygems.org ) .
245-
24691## Contributing
24792
24893Bug reports and pull requests are welcome on GitHub at https://github.com/Syati/structured_params .
0 commit comments