{"id":13878887,"url":"https://github.com/guillaumebriday/jsonapi-scopes","last_synced_at":"2025-09-02T03:42:37.957Z","repository":{"id":56879489,"uuid":"186058471","full_name":"guillaumebriday/jsonapi-scopes","owner":"guillaumebriday","description":"This gem allows you to filter and sort an ActiveRecord relation based on a request, following the JSON:API specification as closely as possible.","archived":false,"fork":false,"pushed_at":"2024-07-11T08:36:31.000Z","size":105,"stargazers_count":33,"open_issues_count":3,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-20T14:51:28.585Z","etag":null,"topics":["json-api","rails-gem"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/jsonapi-scopes","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/guillaumebriday.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"guillaumebriday"}},"created_at":"2019-05-10T21:50:29.000Z","updated_at":"2022-07-16T18:12:25.000Z","dependencies_parsed_at":"2024-10-03T12:48:36.307Z","dependency_job_id":null,"html_url":"https://github.com/guillaumebriday/jsonapi-scopes","commit_stats":{"total_commits":59,"total_committers":1,"mean_commits":59.0,"dds":0.0,"last_synced_commit":"973d24e55222bda489a9399fc5a00011b0eab22d"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/guillaumebriday/jsonapi-scopes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillaumebriday%2Fjsonapi-scopes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillaumebriday%2Fjsonapi-scopes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillaumebriday%2Fjsonapi-scopes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillaumebriday%2Fjsonapi-scopes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guillaumebriday","download_url":"https://codeload.github.com/guillaumebriday/jsonapi-scopes/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guillaumebriday%2Fjsonapi-scopes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273227168,"owners_count":25067684,"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","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["json-api","rails-gem"],"created_at":"2024-08-06T08:02:03.337Z","updated_at":"2025-09-02T03:42:37.906Z","avatar_url":"https://github.com/guillaumebriday.png","language":"Ruby","funding_links":["https://github.com/sponsors/guillaumebriday","https://www.paypal.me/guillaumebriday"],"categories":["Ruby"],"sub_categories":[],"readme":"[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/guillaumebriday)\n![](https://github.com/guillaumebriday/jsonapi-scopes/workflows/Lint/badge.svg)\n![](https://github.com/guillaumebriday/jsonapi-scopes/workflows/Test/badge.svg)\n[![](https://img.shields.io/gem/dt/jsonapi-scopes.svg)](https://rubygems.org/gems/jsonapi-scopes)\n[![](https://img.shields.io/gem/v/jsonapi-scopes.svg)](https://rubygems.org/gems/jsonapi-scopes)\n[![](https://img.shields.io/github/license/guillaumebriday/jsonapi-scopes.svg)](https://github.com/guillaumebriday/jsonapi-scopes)\n\n# Jsonapi::Scopes\nThis gem provides a set of methods which allows you to include, filter and sort an ActiveRecord relation based on a request. It's built to be a simple, robust and scalable system. It follows the [JSON:API specification](https://jsonapi.org/) as closely as possible.\n\nIt's also an unopinionated solution to help you follow the `JSON:API specification`. It doesn't care about how you want to handle the results.\n\nMoreover, it integrates seamlessly into your Rails application while not being a full library.\n\n## Installation\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'jsonapi-scopes'\n```\n\nAnd then execute:\n```bash\n$ bundle\n```\n\n## Usage\n\n### Filter\nThis gem supports [filtering](https://jsonapi.org/format/#fetching-filtering).\n\nThe gem add a `filter` method to define public scopes.\nIt acts as a regular scope.\n\n```ruby\nclass Contact \u003c ActiveRecord::Base\n  include Jsonapi::Filter\n\n  # Respond to `apply_filter`\n  filter :first_name, -\u003e(value) {\n    where(first_name: value)\n  }\n\n  # Do NOT respond to `apply_filter`\n  scope :last_name, -\u003e(value) {\n    where(last_name: value)\n  }\nend\n```\n\nYou can use `apply_filter` in your controller to use the scopes defined with the previous `filter` method:\n\n```ruby\nclass ContactsController \u003c ApplicationController\n  def index\n    @contacts = Contact.apply_filter(params)\n  end\nend\n```\n\nThen you can hit `/contacts?filter[first_name]=Bruce` to filter contacts where the first name exactly match `Bruce`.\n\nYou can specify multiple matching filter values by passing a comma separated list of values: `/contacts?filter[first_name]=Bruce,Peter` will returns contacts where the first name exactly match `Bruce` or `Peter`.\n\nBut `/contacts?filter[last_name]=Wayne` will be completely ignored.\n\n### Sorting\nThis gem supports [sorting](https://jsonapi.org/format/#fetching-sorting).\n\nThe gem add `default_sort` and `sortable_fields` methods to control sort options. They can be overridden in controllers.\n\n```ruby\nclass Contact \u003c ActiveRecord::Base\n  include Jsonapi::Sort\n\n  sortable_fields :lastname, :firstname # List of allowed attributes\n  default_sort lastname: :desc, firstname: :asc # default hash with attributes and directions\nend\n```\n\nYou can use `apply_sort` in your controller:\n\n```ruby\nclass ContactsController \u003c ApplicationController\n  def index\n    @contacts = Contact.apply_sort(params)\n    @contacts = Contact.apply_sort # to only apply default sort\n  end\nend\n```\n\n`apply_sort` accepts a second parameter to override data set with `sortable_fields` and `default_sort` for a specific controller.\n```ruby\nclass ContactsController \u003c ApplicationController\n  def index\n    @contacts = Contact.apply_sort(params, allowed: :full_name, default: { full_name: :desc })\n    # Or @contacts = Contact.apply_sort(params, allowed: [:lastname, :full_name], default: { full_name: :desc })\n  end\nend\n```\n\nThen you can hit `/contacts?sort=lastname` to sort contacts by lastname.\n\nOr use negative sort `/contacts?sort=-firstname` to sort by firstname in `desc` direction.\n\nYou can even combine multiple sort `/contacts?sort=lastname,-firstname`\n\n\n### Included relationships\nThis gem supports [request include params](https://jsonapi.org/format/#fetching-includes). It's very useful when you need to load related resources on client side.\n\n```ruby\nclass Post \u003c ActiveRecord::Base\n  include Jsonapi::Include\n\n  has_many :comments\n  belongs_to :author\n\n  allowed_includes 'comments', 'author.posts' # List of allowed includes\nend\n```\n\nYou can use `apply_include` in your controller:\n\n```ruby\nclass PostsController \u003c ApplicationController\n  def index\n    @posts = Post.apply_include(params)\n  end\nend\n```\n\n`apply_include` accepts a second parameter to override data set with `allowed_includes` for a specific controller.\n```ruby\nclass PostsController \u003c ApplicationController\n  def index\n    @posts = Post.apply_include(params, allowed: 'comments') # to allow only comments.\n    # Or @posts = Post.apply_include(params, allowed: ['comments', 'author'])\n  end\nend\n```\n\nThen you can hit `/posts?include=comments`. You can even combine multiple includes like `/posts?include=comments,author`.\n\nThe gem only handle `include` on the ActiveRecord level. If you want to serialize the data, you must do it in your controller.\n\n#### Nested relationships\n\nYou can load nested relationships using the dot `.` notation:\n\n`/posts?include=author.posts`.\n\n### Rescuing a Bad Request in Rails\n\nJsonapi::scope raises a `Jsonapi::InvalidAttributeError` you can [rescue_from](https://guides.rubyonrails.org/action_controller_overview.html#rescue-from) in your `ApplicationController`.\n\nIf you want to follow the specification, you **must** respond with a `400 Bad Request`.\n\n```ruby\nclass ApplicationController \u003c ActionController::Base\n rescue_from Jsonapi::InvalidAttributeError, with: :json_api_bad_request\n\n private\n\n  def json_api_bad_request(exception)\n    render json: { error: exception.message }, status: :bad_request\n  end\nend\n```\n\n## Contributing\nDo not hesitate to contribute to the project by adapting or adding features ! Bug reports or pull requests are welcome.\n\n## Credits\n\nInspired by:\n\n+ [https://github.com/stefatkins/rails-starter-api](https://github.com/stefatkins/rails-starter-api)\n+ [https://github.com/cerebris/jsonapi-resources](https://github.com/cerebris/jsonapi-resources)\n\n## License\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%2Fguillaumebriday%2Fjsonapi-scopes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguillaumebriday%2Fjsonapi-scopes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguillaumebriday%2Fjsonapi-scopes/lists"}