better_controller 0.1.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.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.rspec +3 -0
- data/.rubocop.yml +95 -0
- data/CHANGELOG.md +18 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +624 -0
- data/Rakefile +12 -0
- data/examples/api_controller.rb +31 -0
- data/examples/application_controller.rb +51 -0
- data/examples/products_controller.rb +25 -0
- data/examples/user_serializer.rb +15 -0
- data/examples/user_service.rb +31 -0
- data/examples/users_controller.rb +86 -0
- data/lib/better_controller/action_helpers.rb +76 -0
- data/lib/better_controller/base.rb +61 -0
- data/lib/better_controller/configuration.rb +69 -0
- data/lib/better_controller/logging.rb +101 -0
- data/lib/better_controller/method_not_overridden_error.rb +13 -0
- data/lib/better_controller/pagination.rb +44 -0
- data/lib/better_controller/parameter_validation.rb +86 -0
- data/lib/better_controller/params_helpers.rb +109 -0
- data/lib/better_controller/railtie.rb +18 -0
- data/lib/better_controller/resources_controller.rb +263 -0
- data/lib/better_controller/response_helpers.rb +74 -0
- data/lib/better_controller/serializer.rb +85 -0
- data/lib/better_controller/service.rb +94 -0
- data/lib/better_controller/version.rb +5 -0
- data/lib/better_controller.rb +55 -0
- data/lib/generators/better_controller/controller_generator.rb +65 -0
- data/lib/generators/better_controller/install_generator.rb +22 -0
- data/lib/generators/better_controller/templates/README +87 -0
- data/lib/generators/better_controller/templates/controller.rb +78 -0
- data/lib/generators/better_controller/templates/initializer.rb +31 -0
- data/lib/generators/better_controller/templates/serializer.rb +32 -0
- data/lib/generators/better_controller/templates/service.rb +57 -0
- data/lib/tasks/better_controller_tasks.rake +61 -0
- data/sig/better_controller.rbs +4 -0
- metadata +226 -0
data/README.md
ADDED
@@ -0,0 +1,624 @@
|
|
1
|
+
# BetterController 🎮
|
2
|
+
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
4
|
+
[](https://github.com/rubocop/rubocop)
|
5
|
+
|
6
|
+
> 🚀 A powerful Ruby gem for building standardized, maintainable, and feature-rich Rails controllers
|
7
|
+
|
8
|
+
BetterController simplifies the process of building RESTful controllers in your Rails applications. It provides a structured approach to define controllers, services, and serializers, making your development process more maintainable and efficient.
|
9
|
+
|
10
|
+
## ✨ Key Features
|
11
|
+
|
12
|
+
- 🏗️ **Standardized Controller Structure**: Define RESTful controllers with minimal code
|
13
|
+
- 🛠️ **Service Layer**: Separate business logic from controllers
|
14
|
+
- 📦 **Serialization**: Standardized JSON serialization for your resources
|
15
|
+
- 📄 **Pagination**: Built-in pagination support for collections
|
16
|
+
- 🔍 **Parameter Validation**: Robust parameter validation and type casting
|
17
|
+
- 🔄 **Response Handling**: Consistent JSON responses with standardized structure
|
18
|
+
- 🚨 **Error Handling**: Comprehensive error handling with custom error classes
|
19
|
+
- 📝 **Logging**: Enhanced logging capabilities
|
20
|
+
- 🧩 **Generators**: Rails generators for controllers, services, and serializers
|
21
|
+
|
22
|
+
## Why BetterController? 🤔
|
23
|
+
|
24
|
+
- 🏗️ **Standardized Approach**: Consistent controller structure across your application
|
25
|
+
- 🧩 **Modular Design**:
|
26
|
+
- Separate controller, service, and serializer components
|
27
|
+
- Reusable modules
|
28
|
+
- Configurable behavior
|
29
|
+
- 🔄 **Flexible Implementation**:
|
30
|
+
- Override default behavior when needed
|
31
|
+
- Customize actions and responses
|
32
|
+
- Extend with your own functionality
|
33
|
+
- ✅ **Robust Error Handling**:
|
34
|
+
- Standardized error responses
|
35
|
+
- Detailed error logging
|
36
|
+
- Custom error classes
|
37
|
+
- 📊 **Enhanced Responses**:
|
38
|
+
- Consistent JSON structure
|
39
|
+
- Pagination metadata
|
40
|
+
- Custom response formatting
|
41
|
+
|
42
|
+
## Installation
|
43
|
+
|
44
|
+
Add the gem to your Gemfile:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
gem 'better_controller'
|
48
|
+
```
|
49
|
+
|
50
|
+
Then run:
|
51
|
+
|
52
|
+
```bash
|
53
|
+
bundle install
|
54
|
+
```
|
55
|
+
|
56
|
+
Or install the gem manually:
|
57
|
+
|
58
|
+
```bash
|
59
|
+
gem install better_controller
|
60
|
+
```
|
61
|
+
|
62
|
+
## Configuration
|
63
|
+
|
64
|
+
In a Rails application, you can create an initializer by running:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
rails generate better_controller:install
|
68
|
+
```
|
69
|
+
|
70
|
+
This command creates the file `config/initializers/better_controller.rb` with a default configuration. An example configuration is:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
BetterController.configure do |config|
|
74
|
+
# Pagination configuration
|
75
|
+
config[:pagination] = {
|
76
|
+
enabled: true,
|
77
|
+
per_page: 25
|
78
|
+
}
|
79
|
+
|
80
|
+
# Serialization configuration
|
81
|
+
config[:serialization] = {
|
82
|
+
include_root: false,
|
83
|
+
camelize_keys: true
|
84
|
+
}
|
85
|
+
|
86
|
+
# Error handling configuration
|
87
|
+
config[:error_handling] = {
|
88
|
+
log_errors: true,
|
89
|
+
detailed_errors: true
|
90
|
+
}
|
91
|
+
end
|
92
|
+
```
|
93
|
+
|
94
|
+
## Generators
|
95
|
+
|
96
|
+
BetterController provides several generators to help you quickly scaffold your application:
|
97
|
+
|
98
|
+
### Install Generator
|
99
|
+
|
100
|
+
Creates an initializer with default configuration:
|
101
|
+
|
102
|
+
```bash
|
103
|
+
rails generate better_controller:install
|
104
|
+
```
|
105
|
+
|
106
|
+
### Controller Generator
|
107
|
+
|
108
|
+
Generates a controller with optional service and serializer:
|
109
|
+
|
110
|
+
```bash
|
111
|
+
rails generate better_controller:controller Users index show create update destroy
|
112
|
+
```
|
113
|
+
|
114
|
+
Options:
|
115
|
+
- `--skip-service`: Skip generating a service class
|
116
|
+
- `--skip-serializer`: Skip generating a serializer class
|
117
|
+
- `--model=MODEL_NAME`: Specify a custom model name (defaults to singular of controller name)
|
118
|
+
|
119
|
+
This will create:
|
120
|
+
- `app/controllers/users_controller.rb`
|
121
|
+
- `app/services/user_service.rb` (unless `--skip-service` is specified)
|
122
|
+
- `app/serializers/user_serializer.rb` (unless `--skip-serializer` is specified)
|
123
|
+
|
124
|
+
## Basic Usage
|
125
|
+
|
126
|
+
### Controller Setup
|
127
|
+
|
128
|
+
Include BetterController in your ApplicationController:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
class ApplicationController < ActionController::Base
|
132
|
+
include BetterController
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
### Creating a ResourcesController
|
137
|
+
|
138
|
+
Create a controller that inherits from the ResourcesController:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
class UsersController < BetterController::ResourcesController
|
142
|
+
# Controller-specific configuration
|
143
|
+
def resource_class
|
144
|
+
User
|
145
|
+
end
|
146
|
+
|
147
|
+
def resource_params
|
148
|
+
params.require(:user).permit(:name, :email, :role)
|
149
|
+
end
|
150
|
+
|
151
|
+
def resource_creator
|
152
|
+
UserService.create(resource_params)
|
153
|
+
end
|
154
|
+
|
155
|
+
def resource_updater
|
156
|
+
UserService.update(@resource, resource_params)
|
157
|
+
end
|
158
|
+
|
159
|
+
def resource_destroyer
|
160
|
+
UserService.destroy(@resource)
|
161
|
+
end
|
162
|
+
|
163
|
+
def index_serializer
|
164
|
+
UserSerializer
|
165
|
+
end
|
166
|
+
|
167
|
+
def show_serializer
|
168
|
+
UserSerializer
|
169
|
+
end
|
170
|
+
|
171
|
+
def create_serializer
|
172
|
+
UserSerializer
|
173
|
+
end
|
174
|
+
|
175
|
+
def update_serializer
|
176
|
+
UserSerializer
|
177
|
+
end
|
178
|
+
|
179
|
+
def destroy_serializer
|
180
|
+
UserSerializer
|
181
|
+
end
|
182
|
+
|
183
|
+
def create_message
|
184
|
+
'User created successfully'
|
185
|
+
end
|
186
|
+
|
187
|
+
def update_message
|
188
|
+
'User updated successfully'
|
189
|
+
end
|
190
|
+
|
191
|
+
def destroy_message
|
192
|
+
'User deleted successfully'
|
193
|
+
end
|
194
|
+
end
|
195
|
+
```
|
196
|
+
|
197
|
+
### Service Layer
|
198
|
+
|
199
|
+
Create a service class to handle business logic:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
class UserService
|
203
|
+
def self.create(params)
|
204
|
+
user = User.new(params)
|
205
|
+
user.save
|
206
|
+
user
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.update(user, params)
|
210
|
+
user.update(params)
|
211
|
+
user
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.destroy(user)
|
215
|
+
user.destroy
|
216
|
+
user
|
217
|
+
end
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
221
|
+
### Serializer
|
222
|
+
|
223
|
+
Create a serializer to format your responses:
|
224
|
+
|
225
|
+
```ruby
|
226
|
+
class UserSerializer
|
227
|
+
def self.serialize(user, options = {})
|
228
|
+
{
|
229
|
+
id: user.id,
|
230
|
+
name: user.name,
|
231
|
+
email: user.email,
|
232
|
+
role: user.role,
|
233
|
+
created_at: user.created_at,
|
234
|
+
updated_at: user.updated_at
|
235
|
+
}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
```
|
239
|
+
|
240
|
+
## Core Features
|
241
|
+
|
242
|
+
### ResourcesController
|
243
|
+
|
244
|
+
The `ResourcesController` provides a standardized implementation of RESTful actions:
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
# Available actions
|
248
|
+
index # GET /resources
|
249
|
+
show # GET /resources/:id
|
250
|
+
create # POST /resources
|
251
|
+
update # PUT/PATCH /resources/:id
|
252
|
+
destroy # DELETE /resources/:id
|
253
|
+
```
|
254
|
+
|
255
|
+
### Response Handling
|
256
|
+
|
257
|
+
BetterController provides standardized methods for handling responses:
|
258
|
+
|
259
|
+
```ruby
|
260
|
+
# Success response
|
261
|
+
respond_with_success(data, options = {})
|
262
|
+
|
263
|
+
# Error response
|
264
|
+
respond_with_error(errors, options = {})
|
265
|
+
```
|
266
|
+
|
267
|
+
Example response format:
|
268
|
+
|
269
|
+
```json
|
270
|
+
{
|
271
|
+
"data": { ... },
|
272
|
+
"message": "Operation completed successfully",
|
273
|
+
"meta": { ... }
|
274
|
+
}
|
275
|
+
```
|
276
|
+
|
277
|
+
### Pagination
|
278
|
+
|
279
|
+
The `Pagination` module provides pagination functionality for ActiveRecord collections:
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
def index
|
283
|
+
execute_action do
|
284
|
+
collection = paginate(resource_collection_resolver)
|
285
|
+
data = serialize_collection(collection, index_serializer)
|
286
|
+
respond_with_success(data, options: { meta: meta })
|
287
|
+
end
|
288
|
+
end
|
289
|
+
```
|
290
|
+
|
291
|
+
Pagination metadata is included in the response:
|
292
|
+
|
293
|
+
```json
|
294
|
+
{
|
295
|
+
"data": [ ... ],
|
296
|
+
"meta": {
|
297
|
+
"pagination": {
|
298
|
+
"total_count": 100,
|
299
|
+
"total_pages": 4,
|
300
|
+
"current_page": 1,
|
301
|
+
"per_page": 25
|
302
|
+
}
|
303
|
+
}
|
304
|
+
}
|
305
|
+
```
|
306
|
+
|
307
|
+
### Error Handling
|
308
|
+
|
309
|
+
BetterController provides comprehensive error handling:
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
begin
|
313
|
+
# Your code here
|
314
|
+
rescue ActiveRecord::RecordNotFound => e
|
315
|
+
respond_with_error(e.message, status: :not_found)
|
316
|
+
rescue ActionController::ParameterMissing => e
|
317
|
+
respond_with_error(e.message, status: :bad_request)
|
318
|
+
rescue StandardError => e
|
319
|
+
respond_with_error(e.message, status: :internal_server_error)
|
320
|
+
end
|
321
|
+
```
|
322
|
+
|
323
|
+
Error response format:
|
324
|
+
|
325
|
+
```json
|
326
|
+
{
|
327
|
+
"errors": {
|
328
|
+
"base": ["Resource not found"]
|
329
|
+
},
|
330
|
+
"message": "An error occurred",
|
331
|
+
"status": 404
|
332
|
+
}
|
333
|
+
```
|
334
|
+
|
335
|
+
end
|
336
|
+
```
|
337
|
+
|
338
|
+
## Advanced Customization
|
339
|
+
|
340
|
+
### Overriding Default Behavior
|
341
|
+
|
342
|
+
You can override any of the default methods in your controller to customize behavior:
|
343
|
+
|
344
|
+
```ruby
|
345
|
+
class UsersController < BetterController::ResourcesController
|
346
|
+
# Override the default index action
|
347
|
+
def index
|
348
|
+
execute_action do
|
349
|
+
@users = User.where(active: true)
|
350
|
+
data = serialize_collection(@users, index_serializer)
|
351
|
+
respond_with_success(data, options: { meta: { active_count: @users.count } })
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# Override the resource finder method
|
356
|
+
def resource_finder
|
357
|
+
User.includes(:posts, :comments).find(params[:id])
|
358
|
+
end
|
359
|
+
|
360
|
+
# Add custom actions
|
361
|
+
def activate
|
362
|
+
execute_action do
|
363
|
+
@resource = resource_finder
|
364
|
+
@resource.update(active: true)
|
365
|
+
data = serialize_resource(@resource, show_serializer)
|
366
|
+
respond_with_success(data, options: { message: 'User activated successfully' })
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
```
|
371
|
+
|
372
|
+
### Custom Serialization
|
373
|
+
|
374
|
+
You can implement custom serialization logic:
|
375
|
+
|
376
|
+
```ruby
|
377
|
+
class UserSerializer
|
378
|
+
def self.serialize(user, options = {})
|
379
|
+
serialized = {
|
380
|
+
id: user.id,
|
381
|
+
name: user.name,
|
382
|
+
email: user.email
|
383
|
+
}
|
384
|
+
|
385
|
+
# Add additional fields based on options
|
386
|
+
if options[:include_details]
|
387
|
+
serialized.merge!({
|
388
|
+
role: user.role,
|
389
|
+
last_login: user.last_login,
|
390
|
+
created_at: user.created_at
|
391
|
+
})
|
392
|
+
end
|
393
|
+
|
394
|
+
serialized
|
395
|
+
end
|
396
|
+
|
397
|
+
def self.serialize_collection(users, options = {})
|
398
|
+
users.map { |user| serialize(user, options) }
|
399
|
+
end
|
400
|
+
end
|
401
|
+
```
|
402
|
+
|
403
|
+
### Custom Error Handling
|
404
|
+
|
405
|
+
Implement custom error handling in your controllers:
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
class ApplicationController < ActionController::Base
|
409
|
+
include BetterController
|
410
|
+
|
411
|
+
rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
|
412
|
+
rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing
|
413
|
+
rescue_from CustomError::AuthorizationError, with: :handle_authorization_error
|
414
|
+
|
415
|
+
private
|
416
|
+
|
417
|
+
def handle_not_found(exception)
|
418
|
+
respond_with_error(exception.message, status: :not_found, options: { code: 'NOT_FOUND' })
|
419
|
+
end
|
420
|
+
|
421
|
+
def handle_parameter_missing(exception)
|
422
|
+
respond_with_error("Required parameter missing: #{exception.param}", status: :bad_request)
|
423
|
+
end
|
424
|
+
|
425
|
+
def handle_authorization_error(exception)
|
426
|
+
respond_with_error('You are not authorized to perform this action', status: :forbidden)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
```
|
430
|
+
|
431
|
+
## Testing
|
432
|
+
|
433
|
+
BetterController includes RSpec tests to ensure functionality. Run the tests with:
|
434
|
+
|
435
|
+
```bash
|
436
|
+
bundle exec rspec
|
437
|
+
```
|
438
|
+
|
439
|
+
Example test for a controller:
|
440
|
+
|
441
|
+
```ruby
|
442
|
+
RSpec.describe UsersController, type: :controller do
|
443
|
+
describe '#index' do
|
444
|
+
it 'returns a collection of users' do
|
445
|
+
get :index
|
446
|
+
expect(response).to have_http_status(:ok)
|
447
|
+
expect(JSON.parse(response.body)['data']).to be_an(Array)
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
describe '#create' do
|
452
|
+
it 'creates a new user' do
|
453
|
+
post :create, params: { user: { name: 'John Doe', email: 'john@example.com' } }
|
454
|
+
expect(response).to have_http_status(:created)
|
455
|
+
expect(JSON.parse(response.body)['message']).to eq('User created successfully')
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
459
|
+
```
|
460
|
+
|
461
|
+
## Contributing
|
462
|
+
|
463
|
+
1. Fork the repository
|
464
|
+
2. Create your feature branch (`git checkout -b feature/my-new-feature`)
|
465
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
466
|
+
4. Push to the branch (`git push origin feature/my-new-feature`)
|
467
|
+
5. Create a new Pull Request
|
468
|
+
|
469
|
+
## License
|
470
|
+
|
471
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
472
|
+
|
473
|
+
## Advanced Features
|
474
|
+
|
475
|
+
### Pagination
|
476
|
+
|
477
|
+
The `Pagination` module provides pagination functionality for ActiveRecord collections:
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
def index
|
481
|
+
execute_action do
|
482
|
+
collection = User.all
|
483
|
+
@users = paginate(collection, page: params[:page], per_page: 20)
|
484
|
+
respond_with_success(@users)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
```
|
488
|
+
|
489
|
+
### Parameter Helpers
|
490
|
+
|
491
|
+
The `ParamsHelpers` module provides enhanced parameter handling:
|
492
|
+
|
493
|
+
```ruby
|
494
|
+
# Get a typed parameter
|
495
|
+
user_id = param(:user_id, type: :integer)
|
496
|
+
|
497
|
+
# Get a boolean parameter
|
498
|
+
active = boolean_param(:active, default: true)
|
499
|
+
|
500
|
+
# Get a date parameter
|
501
|
+
start_date = date_param(:start_date)
|
502
|
+
|
503
|
+
# Get a JSON parameter
|
504
|
+
data = json_param(:data)
|
505
|
+
```
|
506
|
+
|
507
|
+
### Logging
|
508
|
+
|
509
|
+
The `Logging` module provides enhanced logging capabilities:
|
510
|
+
|
511
|
+
```ruby
|
512
|
+
# Log at different levels
|
513
|
+
log_info("Processing request")
|
514
|
+
log_debug("Debug information")
|
515
|
+
log_warn("Warning message")
|
516
|
+
log_error("Error occurred")
|
517
|
+
|
518
|
+
# Log with tags
|
519
|
+
log_info("User created", { user_id: user.id, email: user.email })
|
520
|
+
|
521
|
+
# Log exceptions
|
522
|
+
begin
|
523
|
+
# Some code that might raise an exception
|
524
|
+
rescue => e
|
525
|
+
log_exception(e, { controller: self.class.name, action: action_name })
|
526
|
+
end
|
527
|
+
```
|
528
|
+
|
529
|
+
## Generators
|
530
|
+
|
531
|
+
### Controller Generator
|
532
|
+
|
533
|
+
Generate a controller with BetterController:
|
534
|
+
|
535
|
+
```bash
|
536
|
+
rails generate better_controller:controller Users index show create update destroy
|
537
|
+
```
|
538
|
+
|
539
|
+
This will create:
|
540
|
+
- A UsersController with the specified actions
|
541
|
+
- A UserService for handling business logic
|
542
|
+
- A UserSerializer for serializing responses
|
543
|
+
|
544
|
+
## Example Implementation
|
545
|
+
|
546
|
+
### Controller
|
547
|
+
|
548
|
+
```ruby
|
549
|
+
class UsersController < ApplicationController
|
550
|
+
include BetterController::ResourcesController
|
551
|
+
|
552
|
+
# GET /users
|
553
|
+
def index
|
554
|
+
execute_action do
|
555
|
+
@resource_collection = resource_collection_resolver
|
556
|
+
data = serialize_resource(@resource_collection, index_serializer)
|
557
|
+
respond_with_success(data, options: { meta: meta })
|
558
|
+
end
|
559
|
+
end
|
560
|
+
|
561
|
+
# GET /users/:id
|
562
|
+
def show
|
563
|
+
execute_action do
|
564
|
+
@resource = resource_resolver
|
565
|
+
data = serialize_resource(@resource, show_serializer)
|
566
|
+
respond_with_success(data)
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
# POST /users
|
571
|
+
def create
|
572
|
+
execute_action do
|
573
|
+
@resource = resource_service.create(resource_params)
|
574
|
+
data = serialize_resource(@resource, create_serializer)
|
575
|
+
respond_with_success(data, status: :created)
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
# PATCH/PUT /users/:id
|
580
|
+
def update
|
581
|
+
execute_action do
|
582
|
+
@resource = resource_resolver
|
583
|
+
resource_service.update(@resource, resource_params)
|
584
|
+
data = serialize_resource(@resource, update_serializer)
|
585
|
+
respond_with_success(data)
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
# DELETE /users/:id
|
590
|
+
def destroy
|
591
|
+
execute_action do
|
592
|
+
@resource = resource_resolver
|
593
|
+
resource_service.destroy(@resource)
|
594
|
+
respond_with_success(nil, status: :no_content)
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
protected
|
599
|
+
|
600
|
+
def resource_service_class
|
601
|
+
UserService
|
602
|
+
end
|
603
|
+
|
604
|
+
def resource_params_root_key
|
605
|
+
:user
|
606
|
+
end
|
607
|
+
|
608
|
+
def resource_serializer
|
609
|
+
UserSerializer
|
610
|
+
end
|
611
|
+
end
|
612
|
+
```
|
613
|
+
|
614
|
+
## Contributing 🤝
|
615
|
+
|
616
|
+
1. Fork the repository
|
617
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
618
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
619
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
620
|
+
5. Open a Pull Request
|
621
|
+
|
622
|
+
## License 📄
|
623
|
+
|
624
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Example of an API controller using BetterController
|
4
|
+
class ApiController < ActionController::API
|
5
|
+
include BetterController
|
6
|
+
|
7
|
+
# Global error handling for API controllers
|
8
|
+
rescue_from ActiveRecord::RecordNotFound do |exception|
|
9
|
+
respond_with_error(exception, status: :not_found)
|
10
|
+
end
|
11
|
+
|
12
|
+
rescue_from ActiveRecord::RecordInvalid do |exception|
|
13
|
+
respond_with_error(exception, status: :unprocessable_entity)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Helper method for authentication
|
17
|
+
def authenticate_api_user!
|
18
|
+
token = request.headers['Authorization']&.split&.last
|
19
|
+
|
20
|
+
return if valid_token?(token)
|
21
|
+
|
22
|
+
respond_with_error('Unauthorized access', status: :unauthorized)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def valid_token?(token)
|
28
|
+
# Implementation of token validation logic
|
29
|
+
token.present? && ApiToken.exists?(token: token)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ApplicationController < ActionController::Base
|
4
|
+
include BetterController
|
5
|
+
|
6
|
+
# Handle common exceptions with custom responses
|
7
|
+
rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
|
8
|
+
rescue_from ActiveRecord::RecordInvalid, with: :handle_validation_error
|
9
|
+
rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
# Handle record not found errors
|
14
|
+
def handle_not_found(exception)
|
15
|
+
log_exception(exception)
|
16
|
+
respond_with_error(
|
17
|
+
message: 'Resource not found',
|
18
|
+
details: exception.message,
|
19
|
+
status: :not_found
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Handle validation errors
|
24
|
+
def handle_validation_error(exception)
|
25
|
+
log_exception(exception)
|
26
|
+
respond_with_error(
|
27
|
+
message: 'Validation failed',
|
28
|
+
details: exception.record.errors.full_messages,
|
29
|
+
status: :unprocessable_entity
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Handle missing parameters
|
34
|
+
def handle_parameter_missing(exception)
|
35
|
+
log_exception(exception)
|
36
|
+
respond_with_error(
|
37
|
+
message: 'Missing parameter',
|
38
|
+
details: exception.message,
|
39
|
+
status: :bad_request
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Add custom metadata to responses
|
44
|
+
def meta
|
45
|
+
{
|
46
|
+
app_version: '1.0.0',
|
47
|
+
api_version: 'v1',
|
48
|
+
timestamp: Time.current,
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|