{"id":15554165,"url":"https://github.com/kalidasmuthusamy/rails-api-response-builder","last_synced_at":"2025-04-13T19:40:52.254Z","repository":{"id":62553381,"uuid":"114540181","full_name":"kalidasmuthusamy/rails-api-response-builder","owner":"kalidasmuthusamy","description":"API Response Builder for Rails API app","archived":false,"fork":false,"pushed_at":"2018-03-14T05:54:09.000Z","size":21,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-04-23T03:04:07.581Z","etag":null,"topics":["api-wrapper","rails-gem","rails5-api","ruby","ruby-on-rails","serializer"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kalidasmuthusamy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-17T13:52:12.000Z","updated_at":"2023-03-27T11:26:38.000Z","dependencies_parsed_at":"2022-11-03T04:30:28.725Z","dependency_job_id":null,"html_url":"https://github.com/kalidasmuthusamy/rails-api-response-builder","commit_stats":null,"previous_names":["kalidasm/rails-api-response-builder"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kalidasmuthusamy%2Frails-api-response-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kalidasmuthusamy%2Frails-api-response-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kalidasmuthusamy%2Frails-api-response-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kalidasmuthusamy%2Frails-api-response-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kalidasmuthusamy","download_url":"https://codeload.github.com/kalidasmuthusamy/rails-api-response-builder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248770179,"owners_count":21158928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-wrapper","rails-gem","rails5-api","ruby","ruby-on-rails","serializer"],"created_at":"2024-10-02T14:50:55.142Z","updated_at":"2025-04-13T19:40:52.231Z","avatar_url":"https://github.com/kalidasmuthusamy.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Api::ResponseBuilder\n\nModule to build response object for Rails 5 API Applications.\nDepends on `active_model_serializers` gem.\n\nPass a valid / invalid ActiveRecord object or an instance of ActiveRecord::Relation and get response object in following structure.\n\nProperties | Description\n------------ | -------------\nstatus | 'failure' (or) 'success'\nbody | Serialized Object\nmessages | Error Description (if any)\nstatus_code | HTTP Status Code\n\n\n## Example\n\n```ruby\n#app/controllers/api/v1/application_controller.rb\nmodule Api\n  module V1\n    class ApplicationController \u003c ActionController::API\n\n      def serializer_responder(resource, config = {})\n        response = ::Api::ResponseBuilder::Main.new(resource, config, params).response\n        render json: response, status: response[:status_code]\n      end\n\n    end\n  end\nend\n\n# app/serializers/v1/user_serializer.rb\nmodule V1\n  # Serializer for User model\n  class UserSerializer \u003c ::ActiveModel::Serializer\n    attributes :id,\n      :firstname,\n      :lastname,\n      :phone_number,\n      :email\n  end\nend\n\n\n# app/controllers/api/v1/users_controller.rb\nmodule Api\n  module V1\n    # Defines endpoints for CRUD operations on user model\n    class UsersController \u003c ::Api::V1::ApplicationController\n\n      def index\n        users = User.all\n        serializer_responder(users, serializer: ::V1::UserSerializer)\n      end\n\n    end\n  end\nend\n\n```\n\nResponse Object for API endpoint `/api/v1/users` will be\n\n```json\n{\n  \"status\": \"success\", \n  \"body\" :  \n    [\n      {\n        \"id\": 1,\n        \"firstname\": \"Kalidas\",\n        \"lastname\": \"M\",\n        \"phone_number\": \"+919876543210\",\n        \"email\": \"kalidasm610@gmail.com\"\n      },\n      {\n        \"id\": 2,\n        \"firstname\": \"Dass\",\n        \"lastname\": \"Mk\",\n        \"phone_number\": \"+919876543211\",\n        \"email\": \"\"\n      }\n    ],\n  \"status_code\": \"ok\"\n}\n```\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'api-response_builder'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install api-response_builder\n\n## Usage\n\n#### ApplicationController - Setup\nBy taking advantage of Ruby's inheritance and Rails's app structure, few instance methods in application controller can be used to handle all scenarios for rendering json response across entire application.\n\n```ruby\n  module Api\n    module V1\n      class ApplicationController \u003c ActionController::API\n        # action callbacks\n\n        # Global Exception Handler for Api Exceptions and StandardError\n        rescue_from ::Api::Exception, StandardError do |e|\n          handle_api_exception(e)\n        end\n\n        # Global exception handlers for ActiveRecord Exceptions\n        rescue_from ::ActiveRecord::RecordNotFound, with: :render_record_not_found\n        rescue_from ::ActiveRecord::RecordInvalid, with: :render_record_invalid\n        rescue_from ::ActiveRecord::RecordNotDestroyed, with: :render_forbidden\n\n        # Public methods\n        def handle_api_exception(e)\n          response = ::Api::ResponseBuilder::Main.new(e, {}, params).response\n          render json: response, status: response[:status_code]\n        end\n\n        def render_record_not_found\n          handle_api_exception ::Api::Exception.new(\n            ::Api::Exception.record_not_found\n          )\n        end\n\n        def render_internal_server_error\n          handle_api_exception ::Api::Exception.new(\n            ::Api::Exception.internal_server_error\n          )\n        end\n\n        def render_record_invalid(e)\n          # If exception message is not included in arguments, locale message\n          # (if present) for record invalid exception will be returned in resp\n          exception_message = e.record.errors.full_messages\n          exception = ::Api::Exception.new(\n            ::Api::Exception.record_invalid, exception_message\n          )\n          handle_api_exception(exception)\n        end\n\n        def render_forbidden\n          handle_api_exception ::Api::Exception.new(\n            ::Api::Exception.forbidden_resource\n          )\n        end\n\n        def serializer_responder(resource, config = {})\n          response = ::Api::ResponseBuilder::Main.new(resource, config, params).response\n          # response object also contains corresponding http status code under the key :status_code\n          # Including `Http Status Code` as part of API response is generally considered as good practice\n          # If all your api responses should have `200 OK` as status code, omit status key in render method\n          # Rails, by default, set status code as `200 OK`\n          render json: response, status: response[:status_code]\n        end\n      end\n    end\n  end\n\n```\n\n\n#### Passing Additional Information to Response\n\nIn some cases, meta information may be passed along with response. For example, passing total count of resources for pagination.\n\nIn order to pass meta info, include `:meta` key-value pair in config object passed to `::Api::ResponseBuilder::Main`.\nIt will be reflected in response object under `meta` key\n\nNote: \n  * config[:serializer] should be `ActiveModel::Serializer` class (if serializer is not passed, it will serialize entire object)\n  * `config[:meta]` will accept only hash\n\n\n```ruby\n  # app/controllers/api/v1/users_controller.rb\n  def index\n    users = User.all\n\n    config = {}\n    config[:serializer] = UserSerializer\n    config[:meta] = { total_count: users.count }\n    serializer_responder(users, config)\n  end\n\n  # simple way\n  serializer_responder(users, { serializer: UserSerializer, meta: { total_count: users.count } })\n```\n\n##### Response\n\n```json\n  {\n  \"status\": \"success\", \n  \"body\" :  \n    [\n      {\n        \"id\": 1,\n        \"firstname\": \"Kalidas\",\n        \"lastname\": \"M\",\n        \"phone_number\": \"+919876543210\",\n        \"email\": \"kalidasm610@gmail.com\"\n      },\n      {\n        \"id\": 2,\n        \"firstname\": \"Dass\",\n        \"lastname\": \"Mk\",\n        \"phone_number\": \"+919876543211\",\n        \"email\": \"\"\n      }\n    ],\n  \"status_code\": \"ok\",\n  \"meta\": {\n    \"total_count\": 2\n  }\n}\n```\n\n\n#### API Exceptions\n\nFollowing exceptions are handled by this gem as there are the most commonly used.\n\nEXCEPTION | HTTP Status Code\n------------ | -------------\nINTERNAL_SERVER_ERROR | :internal_server_error (500)\nRECORD_NOT_FOUND | :not_found (404)\nRECORD_INVALID | ::unprocessable_entity (422)\nRECORD_NOT_DESTROYED | :forbidden (403)\nFORBIDDEN_RESOURCE | :forbidden (403)\nUNAUTHORIZED_ACCESS | :unauthorized (401)\n\nFor detailed information, feel free to dive into the [Code](https://github.com/kalidasm/rails-api-response-builder/blob/master/lib/api/exception.rb)\n\n\n##### Error Messages for API Exceptions\n\nAll the error messages are internalized using `Rails Internationalization (I18n) API`.\n\nExceptional messages are mapped under I18n locales (`en.api_response.messages.#{key}`).\n\nKey represents lower-cased version of exception names listed above.\n\nExample :\n\n```yml\n  en:\n    api_response:\n      messages:\n        internal_server_error: \"Internal server error.\"\n        record_not_found: \"The resource you are looking for does not exist.\"\n        record_invalid: \"Validation Failed\"\n        record_not_destroyed: \"Failed to delete the resource\"\n        forbidden_resource: \"You don't have sufficient privileges to perform this operation\"\n        unauthorized_access: \"You are not authorized to perform this operation\"\n```\n\n##### Raising API Exception inside controller actions\n\n```ruby\n  class CreditsController \u003c ApplicationController\n    before_action :authorize_user, only: :update\n\n    def update\n      @credit.update(credit_params)\n    end\n\n    private\n\n    def authorize_user\n      return if user_authorized?\n\n      # Will be handled by rescue_from methods in application controller\n      raise ::Api::Exception.new(\n        ::Api::Exception.unauthorized_access\n      )\n    end\n  end\n```\n\nResponse would be\n\n```json\n  {\n    \"status\": \"failure\",\n    \"messages\": {\n      \"errors\": [\"You are not authorized to perform this operation\"]\n    },\n    \"status_code\": \"unprocessable_entity\",\n    \"meta\": {}\n  }\n```\n\nIf you want to override the default error message in a specific scenario,\n\n```ruby\n  private\n\n  def authorize_user\n    return if user_authorized?\n\n    raise ::Api::Exception.new(\n      ::Api::Exception.unauthorized_access, \"Looks like you are not authorized to update credit score\"\n    )\n  end\n```\n```json\n  {\n    \"status\": \"failure\",\n    \"messages\": {\n      \"errors\": [\"Looks like you are not authorized to update credit score\"]\n    },\n    \"status_code\": \"unprocessable_entity\",\n    \"meta\": {}\n  }\n```\n\n#### Response Status - Failure / Success\n\nResponse Object contains a key named `status`. It will have only any one of following types\n  * failure\n  * success\n\nStatus will be `failure` when\n  * Resource has any errors\n  * Resource is an instance of `::Api::Exception`\n  * StandardError is raised\n\nStatus will be `success` when\n  * Resource do not have any errors\n  * Resource is *not* an instance of `::Api::Exception`\n  * No Exception been raised\n\n\n## Development\n\nAfter 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.\n\nTo 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/kalidasm/api-response_builder.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkalidasmuthusamy%2Frails-api-response-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkalidasmuthusamy%2Frails-api-response-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkalidasmuthusamy%2Frails-api-response-builder/lists"}