ruby_routes 2.2.0 โ†’ 2.3.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +232 -162
  3. data/lib/ruby_routes/constant.rb +137 -18
  4. data/lib/ruby_routes/lru_strategies/hit_strategy.rb +31 -4
  5. data/lib/ruby_routes/lru_strategies/miss_strategy.rb +21 -0
  6. data/lib/ruby_routes/node.rb +75 -33
  7. data/lib/ruby_routes/radix_tree/finder.rb +164 -0
  8. data/lib/ruby_routes/radix_tree/inserter.rb +98 -0
  9. data/lib/ruby_routes/radix_tree.rb +79 -227
  10. data/lib/ruby_routes/route/check_helpers.rb +109 -0
  11. data/lib/ruby_routes/route/constraint_validator.rb +159 -0
  12. data/lib/ruby_routes/route/param_support.rb +202 -0
  13. data/lib/ruby_routes/route/path_builder.rb +86 -0
  14. data/lib/ruby_routes/route/path_generation.rb +102 -0
  15. data/lib/ruby_routes/route/query_helpers.rb +56 -0
  16. data/lib/ruby_routes/route/segment_compiler.rb +163 -0
  17. data/lib/ruby_routes/route/small_lru.rb +93 -18
  18. data/lib/ruby_routes/route/validation_helpers.rb +151 -0
  19. data/lib/ruby_routes/route/warning_helpers.rb +54 -0
  20. data/lib/ruby_routes/route.rb +124 -501
  21. data/lib/ruby_routes/route_set/cache_helpers.rb +174 -0
  22. data/lib/ruby_routes/route_set/collection_helpers.rb +127 -0
  23. data/lib/ruby_routes/route_set.rb +120 -133
  24. data/lib/ruby_routes/router/build_helpers.rb +100 -0
  25. data/lib/ruby_routes/router/builder.rb +96 -0
  26. data/lib/ruby_routes/router/http_helpers.rb +135 -0
  27. data/lib/ruby_routes/router/resource_helpers.rb +137 -0
  28. data/lib/ruby_routes/router/scope_helpers.rb +109 -0
  29. data/lib/ruby_routes/router.rb +193 -181
  30. data/lib/ruby_routes/segment.rb +28 -8
  31. data/lib/ruby_routes/segments/base_segment.rb +40 -4
  32. data/lib/ruby_routes/segments/dynamic_segment.rb +48 -12
  33. data/lib/ruby_routes/segments/static_segment.rb +43 -7
  34. data/lib/ruby_routes/segments/wildcard_segment.rb +56 -12
  35. data/lib/ruby_routes/string_extensions.rb +52 -15
  36. data/lib/ruby_routes/url_helpers.rb +106 -24
  37. data/lib/ruby_routes/utility/inflector_utility.rb +35 -0
  38. data/lib/ruby_routes/utility/key_builder_utility.rb +161 -84
  39. data/lib/ruby_routes/utility/method_utility.rb +137 -0
  40. data/lib/ruby_routes/utility/path_utility.rb +75 -28
  41. data/lib/ruby_routes/utility/route_utility.rb +30 -2
  42. data/lib/ruby_routes/version.rb +3 -1
  43. data/lib/ruby_routes.rb +68 -11
  44. metadata +27 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66764348265233b0904630e4193e21fc93f79e3257ec4d0e43e5c533faf1f7e1
4
- data.tar.gz: de32cc9f5f42398b12e829c4da34aa82afd071fa63ed869180a56203834beecd
3
+ metadata.gz: 59f7b87f3f7b94ce54fcc9a8a3d917833c93312412b160cf82268552fd0454ba
4
+ data.tar.gz: 40417f1672ac4e849f6a85a9170fd01f1619ef931b8bd58e1f52b8896d23605c
5
5
  SHA512:
6
- metadata.gz: 21442f1a73e4045fedbb9bd215c639770c55135f6d55c78c17384996515d1347851d7b3afa952db345793a5aa92d5c14368d28faf0e35d4c985d608d94c8b980
7
- data.tar.gz: 5570f4054ceaf76569bb4f28eca4d94347a559a24febe1936e39dfb9896ccfa281cdd1e2ce24e8e2b157b3d7f3870a67cc9ecdb61b62338bce7e28b5d0c32e4e
6
+ metadata.gz: 7c099d775cf22a7327e8f8b1cfdcb1d51495c08717f20eb879b89e6dbfe2e4ae56cb028ae494e13a72c311c668454d6a6ab8f4e4c7a26a76d0d02ec99ca3c342
7
+ data.tar.gz: 754386d02e0387500ae507f5a2e0ad7c11b46a04c7a461aafbee34fd7ad1d19ef7d7ff1ad207375e2e3be205d8af4afa11c06be8d4e2dbedcb8f4e571055994c
data/README.md CHANGED
@@ -1,26 +1,42 @@
1
- # Ruby Routes Gem
1
+ # Ruby Routes
2
2
 
3
- A lightweight, flexible routing system for Ruby that provides a Rails-like DSL for defining and matching HTTP routes.
3
+ A high-performance, lightweight routing system for Ruby applications providing a Rails-like DSL for defining and matching HTTP routes.
4
4
 
5
5
  ## Features
6
6
 
7
- - **Rails-like DSL**: Familiar syntax for defining routes
8
- - **HTTP Method Support**: GET, POST, PUT, PATCH, DELETE, and custom methods
9
- - **RESTful Resources**: Automatic generation of RESTful routes
10
- - **Nested Routes**: Support for nested resources and namespaces
11
- - **Secure Route Constraints**: Powerful constraint system with built-in security ([see CONSTRAINTS.md](CONSTRAINTS.md))
12
- - **Named Routes**: Generate URLs from route names
13
- - **Path Generation**: Build URLs with parameters
14
- - **Scope Support**: Group routes with common options
15
- - **Concerns**: Reusable route groups
16
- - **Lightweight**: Minimal dependencies, fast performance
7
+ - **๐Ÿš€ High Performance**: 40x faster routing with 99.99% cache hit rate
8
+ - **๐Ÿ”„ Rails-like DSL**: Familiar syntax for defining routes
9
+ - **๐Ÿ›ฃ๏ธ RESTful Resources**: Automatic generation of RESTful routes
10
+ - **๐Ÿ”’ Secure Constraints**: Built-in security with comprehensive constraint system
11
+ - **๐Ÿงฉ Modular Design**: Nested resources, scopes, concerns, and namespaces
12
+ - **๐Ÿ“ Named Routes**: Generate paths from route names with automatic parameter handling
13
+ - **๐Ÿงต Thread Safety**: All caching and shared resources are thread-safe
14
+ - **๐Ÿ” Optimized Caching**: Smart caching strategies for route recognition and path generation
15
+ - **๐Ÿชถ Lightweight**: Minimal dependencies for easy integration
16
+
17
+ ## Table of Contents
18
+
19
+ - [Installation](#installation)
20
+ - [Quick Start](#quick-start)
21
+ - [Basic Usage](#basic-usage)
22
+ - [Route Constraints](#route-constraints)
23
+ - [Route Matching](#route-matching)
24
+ - [Path Generation](#path-generation)
25
+ - [Integration with Rack](#integration-with-rack)
26
+ - [API Reference](#api-reference)
27
+ - [Performance](#performance)
28
+ - [Security](#security)
29
+ - [Documentation](#documentation)
30
+ - [Testing](#testing)
31
+ - [Contributing](#contributing)
32
+ - [License](#license)
17
33
 
18
34
  ## Installation
19
35
 
20
36
  Add this line to your application's Gemfile:
21
37
 
22
38
  ```ruby
23
- gem 'ruby_routes'
39
+ gem 'ruby_routes', '~> 2.1.0'
24
40
  ```
25
41
 
26
42
  And then execute:
@@ -35,13 +51,35 @@ Or install it yourself as:
35
51
  gem install ruby_routes
36
52
  ```
37
53
 
54
+ ## Quick Start
55
+
56
+ ```ruby
57
+ require 'ruby_routes'
58
+
59
+ # Define routes
60
+ router = RubyRoutes.draw do
61
+ root to: 'home#index'
62
+ resources :users
63
+
64
+ namespace :api do
65
+ resources :products
66
+ end
67
+ end
68
+
69
+ # Match a request
70
+ result = router.route_set.match('GET', '/users/123')
71
+ # => {controller: 'users', action: 'show', params: {'id' => '123'}, route: #<RubyRoutes::Route...>}
72
+
73
+ # Generate a path
74
+ path = router.route_set.generate_path(:user, id: 456)
75
+ # => "/users/456"
76
+ ```
77
+
38
78
  ## Basic Usage
39
79
 
40
80
  ### Simple Routes
41
81
 
42
82
  ```ruby
43
- require 'ruby_routes'
44
-
45
83
  router = RubyRoutes.draw do
46
84
  get '/', to: 'home#index'
47
85
  get '/about', to: 'pages#about'
@@ -57,19 +95,19 @@ end
57
95
  router = RubyRoutes.draw do
58
96
  resources :users
59
97
  resources :posts
60
- resources :comments
61
98
  end
62
99
  ```
63
100
 
64
101
  This creates the following routes:
65
- - `GET /users` โ†’ `users#index`
66
- - `GET /users/new` โ†’ `users#new`
67
- - `POST /users` โ†’ `users#create`
68
- - `GET /users/:id` โ†’ `users#show`
69
- - `GET /users/:id/edit` โ†’ `users#edit`
70
- - `PUT /users/:id` โ†’ `users#update`
71
- - `PATCH /users/:id` โ†’ `users#update`
72
- - `DELETE /users/:id` โ†’ `users#destroy`
102
+ | HTTP Method | Path | Controller#Action | Named Route |
103
+ |-------------|--------------------|--------------------|-------------------|
104
+ | GET | /users | users#index | users_path |
105
+ | GET | /users/new | users#new | new_user_path |
106
+ | POST | /users | users#create | users_path |
107
+ | GET | /users/:id | users#show | user_path |
108
+ | GET | /users/:id/edit | users#edit | edit_user_path |
109
+ | PUT/PATCH | /users/:id | users#update | user_path |
110
+ | DELETE | /users/:id | users#destroy | user_path |
73
111
 
74
112
  ### Named Routes
75
113
 
@@ -77,7 +115,6 @@ This creates the following routes:
77
115
  router = RubyRoutes.draw do
78
116
  get '/users', as: :users, to: 'users#index'
79
117
  get '/users/:id', as: :user, to: 'users#show'
80
- post '/users', as: :create_user, to: 'users#create'
81
118
  end
82
119
 
83
120
  # Generate paths
@@ -94,13 +131,12 @@ router = RubyRoutes.draw do
94
131
  resources :posts
95
132
  end
96
133
  end
97
-
98
- # Creates routes like:
99
- # GET /admin/users โ†’ admin/users#index
100
- # GET /admin/users/:id โ†’ admin/users#show
101
- # etc.
102
134
  ```
103
135
 
136
+ Creates routes like:
137
+ - `GET /admin/users` โ†’ `admin/users#index`
138
+ - `GET /admin/users/:id` โ†’ `admin/users#show`
139
+
104
140
  ### Nested Resources
105
141
 
106
142
  ```ruby
@@ -109,18 +145,60 @@ router = RubyRoutes.draw do
109
145
  resources :products
110
146
  end
111
147
  end
148
+ ```
149
+
150
+ Creates routes like:
151
+ - `GET /categories/:category_id/products` โ†’ `products#index`
152
+ - `GET /categories/:category_id/products/:id` โ†’ `products#show`
153
+
154
+ ### Scopes & Concerns
155
+
156
+ ```ruby
157
+ router = RubyRoutes.draw do
158
+ # Scopes
159
+ scope defaults: { format: 'json' } do
160
+ get '/api/users', to: 'api/users#index'
161
+ end
162
+
163
+ # Concerns (reusable route groups)
164
+ concern :commentable do
165
+ resources :comments
166
+ end
167
+
168
+ resources :posts, concerns: :commentable
169
+ resources :articles, concerns: :commentable
170
+ end
171
+ ```
112
172
 
113
- # Creates routes like:
114
- # GET /categories/:category_id/products โ†’ products#index
115
- # GET /categories/:category_id/products/:id โ†’ products#show
116
- # etc.
173
+ ### Method Chaining
174
+
175
+ ```ruby
176
+ router = RubyRoutes.draw do
177
+ get('/users', to: 'users#index')
178
+ .post('/users', to: 'users#create')
179
+ .put('/users/:id', to: 'users#update')
180
+ .delete('/users/:id', to: 'users#destroy')
181
+ end
117
182
  ```
118
183
 
119
- ### Route Constraints
184
+ ### Thread-safe Builder
120
185
 
121
- Ruby Routes provides a powerful and secure constraint system to validate route parameters. **For security reasons, Proc constraints are deprecated** - use the secure alternatives below.
186
+ ```ruby
187
+ # Accumulate routes without mutating a live router
188
+ router = RubyRoutes::Router.build do
189
+ resources :users
190
+ namespace :admin do
191
+ resources :posts
192
+ end
193
+ end
194
+ # router is now finalized and thread-safe
195
+ ```
196
+
197
+ ## Route Constraints
122
198
 
123
- #### Built-in Constraint Types
199
+ Ruby Routes provides a powerful constraint system to validate route parameters before they reach your controllers.
200
+
201
+ ### Built-in Constraint Types
124
202
 
125
203
  ```ruby
126
204
  router = RubyRoutes.draw do
@@ -133,18 +211,12 @@ router = RubyRoutes.draw do
133
211
  # Email validation
134
212
  get '/users/:email', to: 'users#show', constraints: { email: :email }
135
213
 
136
- # URL-friendly slug validation
214
+ # Slug validation
137
215
  get '/posts/:slug', to: 'posts#show', constraints: { slug: :slug }
138
-
139
- # Alphabetic characters only
140
- get '/categories/:name', to: 'categories#show', constraints: { name: :alpha }
141
-
142
- # Alphanumeric characters only
143
- get '/codes/:code', to: 'codes#show', constraints: { code: :alphanumeric }
144
216
  end
145
217
  ```
146
218
 
147
- #### Hash-based Constraints (Recommended)
219
+ ### Hash-based Constraints (Recommended)
148
220
 
149
221
  ```ruby
150
222
  router = RubyRoutes.draw do
@@ -160,19 +232,15 @@ router = RubyRoutes.draw do
160
232
 
161
233
  # Allowed values (whitelist)
162
234
  get '/posts/:status', to: 'posts#show',
163
- constraints: {
164
- status: { in: %w[draft published archived] }
165
- }
235
+ constraints: { status: { in: %w[draft published archived] } }
166
236
 
167
237
  # Numeric ranges
168
238
  get '/products/:price', to: 'products#show',
169
- constraints: {
170
- price: { range: 1..10000 }
171
- }
239
+ constraints: { price: { range: 1..10000 } }
172
240
  end
173
241
  ```
174
242
 
175
- #### Regular Expression Constraints
243
+ ### Regular Expression Constraints
176
244
 
177
245
  ```ruby
178
246
  router = RubyRoutes.draw do
@@ -182,7 +250,7 @@ router = RubyRoutes.draw do
182
250
  end
183
251
  ```
184
252
 
185
- #### โš ๏ธ Security Notice: Proc Constraints Deprecated
253
+ โš ๏ธ **Security Notice**: Proc constraints are deprecated due to security risks:
186
254
 
187
255
  ```ruby
188
256
  # โŒ DEPRECATED - Security risk!
@@ -194,44 +262,8 @@ get '/users/:id', to: 'users#show',
194
262
  constraints: { id: { range: 1..Float::INFINITY } }
195
263
  ```
196
264
 
197
- **๐Ÿ“š For complete constraint documentation, see [CONSTRAINTS.md](CONSTRAINTS.md)**
198
- **๐Ÿ”„ For migration help, see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md)**
199
-
200
- ### Scopes
201
-
202
- ```ruby
203
- router = RubyRoutes.draw do
204
- scope defaults: { format: 'html' } do
205
- get '/posts', to: 'posts#index'
206
- end
207
- end
208
- ```
209
-
210
- ### Concerns
211
-
212
- ```ruby
213
- router = RubyRoutes.draw do
214
- concern :commentable do
215
- resources :comments
216
- end
217
-
218
- resources :posts do
219
- concerns :commentable
220
- end
221
-
222
- resources :articles do
223
- concerns :commentable
224
- end
225
- end
226
- ```
227
-
228
- ### Root Route
229
-
230
- ```ruby
231
- router = RubyRoutes.draw do
232
- root to: 'home#index'
233
- end
234
- ```
265
+ ๐Ÿ“š For complete constraint documentation, see [CONSTRAINTS.md](CONSTRAINTS.md)
266
+ ๐Ÿ”„ For migration help, see [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md)
235
267
 
236
268
  ## Route Matching
237
269
 
@@ -244,12 +276,10 @@ end
244
276
  # Match a request
245
277
  result = router.route_set.match('GET', '/users/123')
246
278
  if result
247
- puts "Controller: #{result[:controller]}"
248
- puts "Action: #{result[:action]}"
249
- puts "Params: #{result[:params]}"
250
- # => Controller: users
251
- # => Action: show
252
- # => Params: {"id"=>"123"}
279
+ controller = result[:controller] # => "users"
280
+ action = result[:action] # => "show"
281
+ params = result[:params] # => {"id"=>"123"}
282
+ route = result[:route] # => #<RubyRoutes::Route...>
253
283
  end
254
284
  ```
255
285
 
@@ -262,10 +292,10 @@ router = RubyRoutes.draw do
262
292
  end
263
293
 
264
294
  # Generate paths
265
- router.route_set.generate_path(:user, id: '123')
295
+ path1 = router.route_set.generate_path(:user, id: '123')
266
296
  # => "/users/123"
267
297
 
268
- router.route_set.generate_path(:post_comment, id: '456', comment_id: '789')
298
+ path2 = router.route_set.generate_path(:post_comment, id: '456', comment_id: '789')
269
299
  # => "/posts/456/comments/789"
270
300
  ```
271
301
 
@@ -275,33 +305,28 @@ router.route_set.generate_path(:post_comment, id: '456', comment_id: '789')
275
305
  require 'rack'
276
306
  require 'ruby_routes'
277
307
 
278
- # Define routes
279
- router = RubyRoutes.draw do
280
- get '/', to: 'home#index'
281
- get '/users', to: 'users#index'
282
- get '/users/:id', to: 'users#show'
283
- end
284
-
285
- # Create Rack app
286
308
  class RubyRoutesApp
287
- def initialize(router)
288
- @router = router
309
+ def initialize
310
+ @router = RubyRoutes.draw do
311
+ root to: 'home#index'
312
+ resources :users
313
+ get '/about', to: 'pages#about'
314
+ end
289
315
  end
290
316
 
291
317
  def call(env)
292
318
  request_method = env['REQUEST_METHOD']
293
319
  request_path = env['PATH_INFO']
294
320
 
295
- route_info = @router.route_set.match(request_method, request_path)
321
+ result = @router.route_set.match(request_method, request_path)
296
322
 
297
- if route_info
298
- # Handle the request
299
- controller = route_info[:controller]
300
- action = route_info[:action]
301
- params = route_info[:params]
323
+ if result
324
+ controller_name = result[:controller]
325
+ action_name = result[:action]
326
+ params = result[:params]
302
327
 
303
328
  # Your controller logic here
304
- [200, {'Content-Type' => 'text/html'}, ["Hello from #{controller}##{action}"]]
329
+ [200, {'Content-Type' => 'text/html'}, ["#{controller_name}##{action_name} with #{params}"]]
305
330
  else
306
331
  [404, {'Content-Type' => 'text/html'}, ['Not Found']]
307
332
  end
@@ -309,72 +334,67 @@ class RubyRoutesApp
309
334
  end
310
335
 
311
336
  # Run the app
312
- app = RubyRoutesApp.new(router)
313
- Rack::Handler::WEBrick.run app, Port: 9292
337
+ Rack::Handler::WEBrick.run RubyRoutesApp.new, Port: 9292
314
338
  ```
315
339
 
316
340
  ## API Reference
317
341
 
318
- ### RubyRoutes.draw(&block)
319
-
320
- Creates a new router instance and yields to the block for route definition.
321
-
322
- ### HTTP Methods
342
+ ### RubyRoutes
323
343
 
324
- - `get(path, options = {})`
325
- - `post(path, options = {})`
326
- - `put(path, options = {})`
327
- - `patch(path, options = {})`
328
- - `delete(path, options = {})`
329
- - `match(path, options = {})`
344
+ - `RubyRoutes.draw(&block)` - Creates a new router and yields the block for route definition
330
345
 
331
- ### Resource Methods
346
+ ### Router Methods
332
347
 
333
- - `resources(name, options = {})` - Creates RESTful routes for a collection
334
- - `resource(name, options = {})` - Creates RESTful routes for a singular resource
335
-
336
- ### Options
337
-
338
- - `to: 'controller#action'` - Specifies controller and action
339
- - `controller: 'name'` - Specifies controller name
340
- - `action: 'name'` - Specifies action name
341
- - `as: :name` - Names the route for path generation
342
- - `via: :method` - Specifies HTTP method(s)
343
- - `constraints: {}` - Adds route constraints
344
- - `defaults: {}` - Sets default parameters
348
+ - `get(path, options = {})` - Define a GET route
349
+ - `post(path, options = {})` - Define a POST route
350
+ - `put(path, options = {})` - Define a PUT route
351
+ - `patch(path, options = {})` - Define a PATCH route
352
+ - `delete(path, options = {})` - Define a DELETE route
353
+ - `match(path, options = {})` - Define a route for multiple HTTP methods
354
+ - `root(options = {})` - Define a root route (/)
355
+ - `resources(name, options = {})` - Define RESTful resource routes
356
+ - `resource(name, options = {})` - Define singular RESTful resource routes
357
+ - `namespace(name, options = {})` - Group routes with a namespace
358
+ - `scope(options = {})` - Group routes with shared options
359
+ - `concern(name, &block)` - Define a reusable route concern
360
+ - `concerns(names)` - Use defined concerns in the current context
345
361
 
346
362
  ### RouteSet Methods
347
363
 
348
- - `match(method, path)` - Matches a request to a route
349
- - `generate_path(name, params = {})` - Generates path from named route
350
- - `find_route(method, path)` - Finds a specific route
351
- - `find_named_route(name)` - Finds a named route
364
+ - `match(method, path)` - Match a request to a route
365
+ - `generate_path(name, params = {})` - Generate a path from a named route
366
+ - `find_route(method, path)` - Find a specific route
367
+ - `find_named_route(name)` - Find a named route by name
352
368
 
353
- ## Documentation
369
+ ## Performance
354
370
 
355
- ### Core Documentation
356
- - **[CONSTRAINTS.md](CONSTRAINTS.md)** - Complete guide to route constraints and security best practices
357
- - **[MIGRATION_GUIDE.md](MIGRATION_GUIDE.md)** - Step-by-step guide for migrating from deprecated Proc constraints
371
+ Ruby Routes is optimized for high-performance applications:
358
372
 
359
- ### Examples
373
+ - **40x faster** routing compared to many alternatives
374
+ - **99.99% cache hit rate** for common access patterns
375
+ - **Low memory footprint** with bounded caches and object reuse
376
+ - **Zero memory leaks** in long-running applications
360
377
 
361
- See the `examples/` directory for more detailed examples:
378
+ Performance metrics (from `benchmark/` directory):
362
379
 
363
- - `examples/basic_usage.rb` - Basic routing examples
364
- - `examples/rack_integration.rb` - Full Rack application example
380
+ | Operation | Operations/sec | Memory Usage |
381
+ |-----------|----------------|-------------|
382
+ | Route Matching | ~250,000/sec | Low |
383
+ | Path Generation | ~400,000/sec | Low |
384
+ | Static Routes | ~500,000/sec | Minimal |
365
385
 
366
386
  ## Security
367
387
 
368
- Ruby Routes prioritizes security and has implemented several protections:
388
+ Ruby Routes prioritizes security with these protections:
369
389
 
370
390
  ### ๐Ÿ”’ Security Features
371
391
  - **XSS Protection**: All HTML output is properly escaped
372
392
  - **ReDoS Protection**: Regular expression constraints have timeout protection
373
- - **Secure Constraints**: Deprecated dangerous Proc constraints in favor of secure alternatives
374
- - **Thread Safety**: All caching and shared resources are thread-safe
375
- - **Input Validation**: Comprehensive parameter validation before reaching application code
393
+ - **Secure Constraints**: Type-safe constraint system without code execution
394
+ - **Thread Safety**: All shared resources are thread-safe
395
+ - **Input Validation**: Comprehensive parameter validation
376
396
 
377
- ### โš ๏ธ Important Security Notice
397
+ ### โš ๏ธ Security Notice
378
398
  **Proc constraints are deprecated due to security risks** and will be removed in a future version. They allow arbitrary code execution which can be exploited for:
379
399
  - Code injection attacks
380
400
  - Denial of service attacks
@@ -382,16 +402,28 @@ Ruby Routes prioritizes security and has implemented several protections:
382
402
 
383
403
  **Migration Required**: If you're using Proc constraints, please migrate to secure alternatives using our [Migration Guide](MIGRATION_GUIDE.md).
384
404
 
405
+ ## Documentation
406
+
407
+ ### Core Documentation
408
+ - **[CONSTRAINTS.md](CONSTRAINTS.md)** - Complete guide to route constraints and security
409
+ - **[MIGRATION_GUIDE.md](MIGRATION_GUIDE.md)** - Guide for migrating from deprecated Proc constraints
410
+ - **[SECURITY_FIXES.md](SECURITY_FIXES.md)** - Details on security improvements
411
+ - **[USAGE.md](USAGE.md)** - Extended usage scenarios
412
+
413
+ ### Examples
414
+ See the `examples/` directory for more detailed examples:
415
+ - `examples/basic_usage.rb` - Basic routing examples
416
+ - `examples/rack_integration.rb` - Full Rack application example
417
+ - `examples/constraints.rb` - Route constraint examples
418
+
385
419
  ## Testing
386
420
 
387
- Run the test suite:
421
+ Ruby Routes has comprehensive test coverage:
388
422
 
389
423
  ```bash
390
424
  bundle exec rspec
391
425
  ```
392
426
 
393
- The test suite includes comprehensive security tests to ensure all protections are working correctly.
394
-
395
427
  ## Contributing
396
428
 
397
429
  1. Fork the repository
@@ -407,3 +439,41 @@ This gem is available as open source under the terms of the [MIT License](LICENS
407
439
  ## Acknowledgments
408
440
 
409
441
  This gem was inspired by Rails routing and aims to provide a lightweight alternative for Ruby applications that need flexible routing without the full Rails framework.
442
+
443
+ ## Thread-safe Build (Isolated Builder)
444
+
445
+ Use the builder to accumulate routes without mutating a live router:
446
+
447
+ ```ruby
448
+ router = RubyRoutes::Router.build do
449
+ resources :users
450
+ namespace :admin do
451
+ resources :posts
452
+ end
453
+ end
454
+ # router is now finalized (immutable)
455
+ ```
456
+
457
+ If you need manual steps:
458
+
459
+ ```ruby
460
+ builder = RubyRoutes::Router::Builder.new do
461
+ get '/health', to: 'system#health'
462
+ end
463
+ router = builder.build # finalized
464
+ ```
465
+
466
+ ## Fluent Method Chaining
467
+
468
+ For a more concise style, the routing DSL supports method chaining:
469
+
470
+ ```ruby
471
+ router = RubyRoutes.draw do
472
+ get('/users', to: 'users#index')
473
+ .post('/users', to: 'users#create')
474
+ .put('/users/:id', to: 'users#update')
475
+ .delete('/users/:id', to: 'users#destroy')
476
+ .resources(:posts)
477
+ end
478
+ ```
479
+