{"id":16221521,"url":"https://github.com/infinum/infinum-json-api-setup","last_synced_at":"2025-10-15T05:27:39.201Z","repository":{"id":46828537,"uuid":"307989552","full_name":"infinum/infinum-json-api-setup","owner":"infinum","description":null,"archived":false,"fork":false,"pushed_at":"2022-11-10T11:21:04.000Z","size":142,"stargazers_count":1,"open_issues_count":2,"forks_count":1,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-16T00:34:54.448Z","etag":null,"topics":["ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/infinum.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-10-28T11:06:17.000Z","updated_at":"2021-10-25T11:26:15.000Z","dependencies_parsed_at":"2023-01-23T02:00:58.396Z","dependency_job_id":null,"html_url":"https://github.com/infinum/infinum-json-api-setup","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/infinum%2Finfinum-json-api-setup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/infinum%2Finfinum-json-api-setup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/infinum%2Finfinum-json-api-setup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/infinum%2Finfinum-json-api-setup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/infinum","download_url":"https://codeload.github.com/infinum/infinum-json-api-setup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243986093,"owners_count":20379263,"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":["ruby"],"created_at":"2024-10-10T12:08:24.037Z","updated_at":"2025-10-15T05:27:39.087Z","avatar_url":"https://github.com/infinum.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Infinum JSON:API setup\nPreconfigured set of libraries for building JSON:API compliant endpoints, with matchers for writing more declarative JSON:API specs. This library presumes host project is compliant with using\n- [rails](https://github.com/rails/rails) as an application server\n- [jsonapi_parameters](https://github.com/visualitypl/jsonapi_parameters) for incoming data parsing\n- [json_schemer](https://github.com/davishmcclurg/json_schemer) for validating JSON structures\n- [responders](https://github.com/heartcombo/responders) for writing declarative actions\n\n## Installation\n1. Add Infinum JSON:API setup to your Gemfile\n  ```ruby\n  gem 'infinum_json_api_setup'\n  ```\n\n2. Next, run the generator\n  ```bash\n  bundle exec rails generate infinum_json_api_setup:install\n  ```\nThe generator will copy the [default translations](https://github.com/infinum/infinum-json-api-setup/blob/master/lib/generators/infinum_json_api_setup/templates/config/locales/json_api.en.yml) into the host project (`config/locales/json_api.en.yml`), where they can be customized.\n\n## Application configuration\nCreate abstract class for your controllers, include common JSON:API request processing behaviour, and configure responders.\n```ruby\nmodule Api\n  class BaseController \u003c ActionController::API\n    include InfinumJsonApiSetup::JsonApi::ErrorHandling\n    include InfinumJsonApiSetup::JsonApi::ContentNegotiation\n\n    self.responder = InfinumJsonApiSetup::JsonApi::Responder\n    respond_to :json_api\n  end\nend\n```\n\n## Basic usage\n\n### Permitted parameter handling\nUse [jsonapi_parameters](https://github.com/visualitypl/jsonapi_parameters) to transform incoming JSON:API compliant data into common Rails parameters\n```ruby\ndef permitted_params\n  params.from_jsonapi\n        .require(:user)\n        .permit(:first_name, :last_name)\nend\n```\n\n### Responding\nUse `respond_with` to initiate transformation (serialization) of domain objects into HTTP response.\n```ruby\ndef show\n  respond_with User.find(params[:id])\nend\n```\n\n`respond_with` is well integrated with `ActiveRecord::Model` interface. Given a compliant object, the method will correctly set a response status and handle object(or error) serialization based on the presence of `.errors`. For a successful domain operation, HTTP status will be 200 OK (or 201 in case of `create` controller action). Unsuccessful operations will have HTTP status 422 Unprocessable Entity with errors structured according to [JSON:API specification](https://jsonapi.org/format/#error-objects).\n```ruby\ndef create\n  respond_with User.create(permitted_params)\nend\n```\n\n`respond_with` also detects usage from a `destroy` controller action and responds with HTTP status 204 No Content and an empty body.\n```ruby\ndef destroy\n  respond_with User.destroy(params[:id])\nend\n```\n\n## Internals\nThis section explains the under-the-hood behavior of the library.\n\n### Content negotiation\n`InfinumJsonApiSetup::JsonApi::ContentNegotiation` module is designed to integrate [server responsibilities](https://jsonapi.org/format/#content-negotiation-servers) of content negotiation protocol described by the JSON:API specification.\n\n### Error handling\n`InfinumJsonApiSetup::JsonApi::ErrorHandling` module is designed to catch and handle common exceptions that might bubble up when processing a request.\n\n| Exception                                      | HTTP status | Bugsnag notification |\n| ---                                            | :---:       | :---:                |\n| `ActionController::ParameterMissing`           | 400         |                      |\n| `ActionDispatch::Http::Parameters::ParseError` | 400         |                      |\n| `Jure::UnpermittedSortParameters`              | 400         | :white_check_mark:   |\n| `I18n::InvalidLocale`                          | 400         |                      |\n| `Pundit::NotAuthorizedError`                   | 403         | :white_check_mark:   |\n| `ActiveRecord::RecordNotFound`                 | 404         |                      |\n| `PG::Error`                                    | 500         |                      |\n\n### Error serialization\n`InfinumJsonApiSetup::JsonApi::ErrorSerializer` is responsible for serializing domain errors according to [JSON:API specification](https://jsonapi.org/format/#error-objects).\n\n## Testing\n\n### RSpec configuration\nLibrary ships with a set of declarative matchers and request/response helpers. To use them in your specs, configure your RSpec setup in the following way which\n- includes all defined matchers\n- includes request and response helper methods into specs tagged with `:request` metadata\n- configures search paths for resolving JSON schema files\n```ruby\nrequire 'infinum_json_api_setup/rspec'\n\nRSpec.configure do |config|\n  # Helpers\n  config.include InfinumJsonApiSetup::Rspec::Helpers::RequestHelper, type: :request\n  config.include InfinumJsonApiSetup::Rspec::Helpers::ResponseHelper, type: :request\n\n  # Schema paths\n  config.schema_response_root = Rails.application.root.join('path/to/response_schemas')\n  config.schema_request_root = Rails.application.root.join('path/to/request_schemas')\nend\n```\n### Matchers\n\n#### Have empty data\n```ruby\nexpect(response).to have_empty_data\n```\n\n#### Have error pointer\n```ruby\nexpect(response).to have_error_pointer('data/attributes/first_name')\n```\n\n#### Have resource count of\n```ruby\nexpect(response).to have_resource_count_of(3)\n```\n\n#### Include all resource ids\n```ruby\nexpect(response).to include_all_resource_ids(records.map(\u0026:id))\n```\n\n#### Include all resource ids sorted\n```ruby\nexpect(response).to include_all_resource_ids_sorted(records.map(\u0026:id))\n```\n\n#### Include all resource string ids\n```ruby\nexpect(response).to include_all_resource_string_ids(records.map(\u0026:id).map(\u0026:to_s))\n```\n\n#### Include error detail\n```ruby\nexpect(response).to include_error_detail('name has been taken')\n```\n\n#### Include related resource\n```ruby\nexpect(response).to include_related_resource('user', user.id)\n```\n\n## Credits\n**JSON:API setup** is maintained and sponsored by [Infinum](https://infinum.co)\n\n## License\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfinum%2Finfinum-json-api-setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finfinum%2Finfinum-json-api-setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfinum%2Finfinum-json-api-setup/lists"}