Otpor
Otpor is a Rails engine designed to enhance the functionality of JSON responses and handle ActiveRecord validation errors in a more structured and consistent way.
Features
- Custom JSON Responses: Handles the rendering of JSON responses with metadata, status codes, and errors.
- Exception Handling: Catches exceptions and gracefully returns error details in JSON format.
- ActiveRecord Validation Error Logging: Logs validation errors after they occur, providing structured error details for each failed validation.
-
Request Store: Uses
RequestStore
to store request-specific data such as errors, status codes, and exception logs.
Installation
Add Otpor to your application's Gemfile:
gem 'otpor'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install otpor
Usage
JSON Response Module
The JsonResponse
module provides a way to handle JSON responses for your Rails controllers. It captures the status code, renders partials if available, and includes metadata or pagination details when necessary.
Example:
In your controller:
class MyController < ApplicationController
include Otpor::JsonResponse
def show
# Your logic here
end
end
The engine will automatically render a structured JSON response based on the action's results. The following attributes are included:
- status: Includes the name, code, and type of the HTTP status.
- data: Renders partials if they exist for the specific controller action.
- errors: Any errors captured during the request.
- notes: Additional notes, if any.
- meta: Pagination and metadata for the response.
- exception_log: Exception details for development environments.
Rendering Partials in data
To render content inside the data
field of the JSON response, you must create a partial with the same name as the controller action. For example, if you have an action named show
, you should create a partial called _show.json.jbuilder
in the relevant views directory.
Example:
# app/views/my_controller/_show.json.jbuilder
json.extract! @record, :id, :name, :description
When the action executes successfully, this partial will be rendered inside the data
field of the JSON response.
Basic Response Example
Here is an example of a basic JSON response generated by Otpor when there are no errors and a partial exists:
{
"status": {
"name": "OK",
"code": 200,
"type": "Success"
},
"data": {
"id": 1,
"name": "Item 1",
"description": "This is a description."
},
"errors": null,
"notes": null,
"meta": null,
"exception_log": null
}
Paginating with Kaminari
If you are using Kaminari for pagination, Otpor will automatically populate the meta
field in the JSON response with pagination metadata.
Example:
In your controller:
class MyController < ApplicationController
include Otpor::JsonResponse
def index
@items = Item.page(params[:page])
end
end
Example of Paginated JSON Response:
{
"status": {
"name": "OK",
"code": 200,
"type": "Success"
},
"data": [
{ "id": 1, "name": "Item 1" },
{ "id": 2, "name": "Item 2" }
],
"errors": null,
"notes": null,
"meta": {
"pagination": {
"total_pages": 10,
"total_count": 100,
"current_page": 1,
"next_page": 2,
"prev_page": null,
"per_page": 10
}
},
"exception_log": null
}
API Versioning
If you are building an API and need to version your responses, Otpor will automatically include the API version in the JSON response.
Example:
Your URL might look like this: http://example.com/api/v1/items
.
Here is an example of a JSON response with API versioning:
{
"status": {
"name": "OK",
"code": 200,
"type": "Success"
},
"data": [
{ "id": 1, "name": "Item 1" },
{ "id": 2, "name": "Item 2" }
],
"errors": null,
"notes": null,
"meta": {
"api_version": "v1"
},
"exception_log": null
}
ActiveRecord Validation Error Handling
The ActiveRecordValidationError
module logs all validation errors after they occur and stores them in the request for easy access. This module is intended to be included in controllers to handle validation errors from ActiveRecord.
Example:
In your controller:
class MyController < ApplicationController
include Otpor::ActiveRecordValidationError
def create
# Your logic here
@record = MyModel.new(record_params)
if @record.save
# success logic
else
# validation errors will be captured automatically
end
end
end
Whenever validation errors occur, they will be captured and stored in RequestStore
, which can then be accessed and returned in the JSON response.
Example JSON Response for Validation Errors
{
"status": {
"name": "Unprocessable Entity",
"code": 422,
"type": "Client Error"
},
"data": null,
"errors": [
{
"attribute": "name",
"message": "can't be blank",
"type": "validation",
"entity": "MyModel",
"entity_id": "new record"
}
],
"notes": null,
"meta": null,
"exception_log": null
}
Development
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.
To install this gem onto your local machine, run:
$ bundle exec rake install
How to Contribute?
- Fork the project;
- Make the necessary adjustments or improvements along with the corresponding tests;
- Submit a pull request;
Developers
License
This gem is available as open source under the terms of the MIT License.