### Install JSONAPI::Resources via Bundler Source: https://jsonapi-resources.com/v0.10/guide/index After adding the gem to your Gemfile, execute this command to install JSONAPI::Resources and its dependencies. This command reads the Gemfile and installs all specified gems. ```bash bundle ``` -------------------------------- ### Install JSONAPI::Resources via gem install Source: https://jsonapi-resources.com/v0.10/guide/index Alternatively, you can install the JSONAPI::Resources gem directly using the gem install command. This method is useful if you are not managing dependencies through Bundler or want to install a specific version. ```bash gem install jsonapi-resources ``` -------------------------------- ### Install Bundler and Seed Database (Shell) Source: https://jsonapi-resources.com/v0.10/guide/basic_usage These shell commands are used to install the necessary gems for a Rails project using Bundler and then execute the database seeding script. This is a common step in setting up a Rails application with initial data. ```shell bundle install rails db:seed ``` -------------------------------- ### Launch Rails Server Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Starts the Rails development server to run the application. This is a common command for Ruby on Rails projects. ```bash rails server ``` -------------------------------- ### Add JSONAPI-Resources Gem Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Adds the 'jsonapi-resources' gem to the application's Gemfile and then runs bundle to install it. This makes the gem available for use in the application. ```ruby gem 'jsonapi-resources' ``` ```bash bundle ``` -------------------------------- ### Paged Paginator Request Example Source: https://jsonapi-resources.com/v0.10/guide/resources Demonstrates an HTTP GET request using the paged paginator for JSONAPI resources. It specifies the page number and size using URL-encoded query parameters. ```http GET /articles?page%5Bnumber%5D=10&page%5Bsize%5D=10 HTTP/1.1 Accept: application/vnd.api+json ``` -------------------------------- ### Setup JSONAPI Resources Routes Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Adds routes for the `contacts` and `phone_numbers` resources using the `jsonapi_resources` helper. This makes the API endpoints available for these resources. ```ruby jsonapi_resources :contacts jsonapi_resources :phone_numbers ``` -------------------------------- ### Add JSONAPI::Resources to Gemfile Source: https://jsonapi-resources.com/v0.10/guide/index This code snippet shows how to add the jsonapi-resources gem to your application's Gemfile. This is the first step in installing the JR framework for your Rails application. Ensure you are using a compatible version of Rails (4.2+). ```ruby gem 'jsonapi-resources' ``` -------------------------------- ### Provide Controller Context to Resources Source: https://jsonapi-resources.com/v0.10/guide/resources This example shows how to make controller state, like the current user, available to resource classes by implementing a 'context' method in ApplicationController. This context can then be accessed within resource callbacks. ```ruby class ApplicationController < JSONAPI::ResourceController def context {current_user: current_user} end end class PeopleController < ApplicationController end class PeopleResource < JSONAPI::Resource before_save do @model.user_id = context[:current_user].id if @model.new_record? end end ``` -------------------------------- ### API Response for All Contacts Source: https://jsonapi-resources.com/v0.10/guide/basic_usage An example of the HTTP response when querying all contacts. It includes a 200 OK status and a JSON:API array of contact resources. ```http TTP/1.1 200 OK X-Frame-Options: SAMEORIGIN X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Content-Type: application/vnd.api+json Etag: W/"512c3c875409b401c0446945bb40916f" Cache-Control: max-age=0, private, must-revalidate X-Request-Id: b324bff8-8196-4c43-80fd-b2fd1f41c565 X-Runtime: 0.004106 Server: WEBrick/1.3.1 (Ruby/2.2.2/2015-04-13) Date: Thu, 18 Jun 2015 18:23:19 GMT Content-Length: 365 Connection: Keep-Alive {"data":[{"id":"1","type":"contacts","links":{"self":"http://localhost:3000/contacts/1"},"attributes":{"name-first":"John","name-last":"Doe","email":"john.doe@boring.test","twitter":null},"relationships":{"phone-numbers":{"links":{"self":"http://localhost:3000/contacts/1/relationships/phone-numbers","related":"http://localhost:3000/contacts/1/phone-numbers"}}}}]} ``` -------------------------------- ### Offset Paginator Request Example Source: https://jsonapi-resources.com/v0.10/guide/resources Illustrates an HTTP GET request utilizing the offset paginator for JSONAPI resources. It defines the limit and offset for the result set via URL-encoded query parameters. ```http GET /articles?page%5Blimit%5D=10&page%5Boffset%5D=10 HTTP/1.1 Accept: application/vnd.api+json ``` -------------------------------- ### Generate a JSONAPI Resource Source: https://jsonapi-resources.com/v0.10/guide/resources This command demonstrates how to use the jsonapi:resource generator to quickly scaffold a new resource file. It simplifies the initial setup for resource definitions. ```bash rails generate jsonapi:resource contact ``` -------------------------------- ### Custom Resource Finder with Contextual User Source: https://jsonapi-resources.com/v0.10/guide/resources Extends `JSONAPI::Resource` to override the `find` method. This example demonstrates finding resources based on a `current_user` object available in the `options[:context]`, allowing for user-specific data retrieval. ```ruby class AuthorResource < JSONAPI::Resource attribute :name model_name 'Person' has_many :posts filter :name def self.find(filters, options = {}) context = options[:context] authors = context[:current_user].find_authors(filters) return authors.map do |author| self.new(author, context) end end end ``` -------------------------------- ### ResourceSerializer with Options Source: https://jsonapi-resources.com/v0.10/guide/serializer Demonstrates how to use ResourceSerializer with optional parameters like `include` and `fields`. ```APIDOC ## POST /serialize/resource/options ### Description Serializes a resource instance using `ResourceSerializer` with specified options for including related resources and filtering fields. ### Method POST ### Endpoint `/serialize/resource/options` ### Parameters #### Request Body - **resource_type** (string) - Required - The primary resource type to serialize. - **resource_instance** (object) - Required - The resource instance or array of resource instances to serialize. - **context** (object) - Optional - A hash of state to be passed to the resource. - **include** (array) - Optional - An array of resources to be side-loaded. Supports dot notation for nested resources. - **fields** (object) - Optional - A hash of resource types and arrays of fields for each type. Determines which fields are serialized. ### Request Example ```json { "resource_type": "PostResource", "resource_instance": { "id": "1", "title": "New post", "body": "A body!!!", "subject": "New post" }, "context": { "current_user": "user123" }, "include": ["comments", "author", "comments.tags", "author.posts"], "fields": { "people": ["email", "comments"], "posts": ["title", "author"], "tags": ["name"], "comments": ["body", "post"] } } ``` ### Response #### Success Response (200) - **data** (object) - The serialized resource in JSON API format, with included resources and filtered fields as specified. #### Response Example ```json { "data": { "type": "posts", "id": "1", "links": { "self": "http://example.com/posts/1" }, "attributes": { "title": "New post", "author": { "type": "people", "id": "1" } }, "relationships": { "section": { "links": { "self": "http://example.com/posts/1/relationships/section", "related": "http://example.com/posts/1/section" }, "data": null }, "author": { "links": { "self": "http://example.com/posts/1/relationships/author", "related": "http://example.com/posts/1/author" }, "data": { "type": "people", "id": "1" } }, "tags": { "links": { "self": "http://example.com/posts/1/relationships/tags", "related": "http://example.com/posts/1/tags" } }, "comments": { "links": { "self": "http://example.com/posts/1/relationships/comments", "related": "http://example.com/posts/1/comments" } } } }, "included": [ { "type": "people", "id": "1", "attributes": { "email": "author@example.com" } }, { "type": "comments", "id": "10", "attributes": { "body": "Great post!" }, "relationships": { "post": { "data": { "type": "posts", "id": "1" } } } } ] } ``` ``` -------------------------------- ### Create Databases Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Creates the databases for the Rails application. This command is run after the application is generated. ```bash rake db:create ``` -------------------------------- ### Polymorphic Relationship Setup in JSONAPI Resources Source: https://jsonapi-resources.com/v0.10/guide/resources Shows the necessary resource and controller definitions for a polymorphic relationship in JSONAPI Resources. Note that while the resources and controllers must exist, routing to them may cause errors if not properly configured. ```ruby class TaggableResource < JSONAPI::Resource; end class TaggablesController < JSONAPI::ResourceController; end ``` -------------------------------- ### Custom Default Value Formatter Example (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/formatting Illustrates creating a custom default value formatter, `MyDefaultValueFormatter`, that inherits from `DefaultValueFormatter`. This example specifically formats DateTime values to the UTC timezone before applying the default formatting. ```ruby class MyDefaultValueFormatter < DefaultValueFormatter class << self def format(raw_value) case raw_value when DateTime return super(raw_value.in_time_zone('UTC')) else return super end end end end ``` -------------------------------- ### Configure CORS Middleware Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Adds the `rack-cors` middleware to the application's configuration in `config/application.rb`. This example configures it to allow all origins and common HTTP methods, but should be reviewed for specific security needs. ```ruby # Example only, please understand CORS before blindly adding this configuration # This is not enabled in the peeps source code. module Peeps class Application < Rails::Application config.middleware.insert_before 0, 'Rack::Cors', :debug => !Rails.env.production?, :logger => (-> { Rails.logger }) do allow do origins '*' resource '*', :headers => :any, :methods => [:get, :post, :patch, :delete, :options] end end end end ``` -------------------------------- ### ResourceSerializer Serialization Source: https://jsonapi-resources.com/v0.10/guide/serializer Demonstrates how to serialize a single resource instance using ResourceSerializer. ```APIDOC ## POST /serialize/resource ### Description Serializes a single resource instance into JSON API compliant JSON format. ### Method POST ### Endpoint `/serialize/resource` ### Parameters #### Request Body - **resource_type** (string) - Required - The primary resource type to serialize. - **resource_instance** (object) - Required - The resource instance or array of resource instances to serialize. - **context** (object) - Optional - A hash of state to be passed to the resource. ### Request Example ```json { "resource_type": "PostResource", "resource_instance": { "id": "1", "title": "New post", "body": "A body!!!", "subject": "New post" }, "context": { "current_user": "user123" } } ``` ### Response #### Success Response (200) - **data** (object) - The serialized resource in JSON API format. #### Response Example ```json { "data": { "type": "posts", "id": "1", "links": { "self": "http://example.com/posts/1" }, "attributes": { "title": "New post", "body": "A body!!!", "subject": "New post" }, "relationships": { "section": { "links": { "self": "http://example.com/posts/1/relationships/section", "related": "http://example.com/posts/1/section" }, "data": null }, "author": { "links": { "self": "http://example.com/posts/1/relationships/author", "related": "http://example.com/posts/1/author" }, "data": { "type": "people", "id": "1" } }, "tags": { "links": { "self": "http://example.com/posts/1/relationships/tags", "related": "http://example.com/posts/1/tags" } }, "comments": { "links": { "self": "http://example.com/posts/1/relationships/comments", "related": "http://example.com/posts/1/comments" } } } } } ``` ``` -------------------------------- ### Creating a Custom Key Formatter (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/formatting Shows how to create a custom key formatter, `UpperCamelizedKeyFormatter`, by inheriting from `JSONAPI::KeyFormatter`. This example implements a formatter that converts keys to upper camel case. ```ruby class UpperCamelizedKeyFormatter < JSONAPI::KeyFormatter class << self def format(key) super.camelize(:upper) end end end ``` -------------------------------- ### Request Included Relationships (Side-loading) in HTTP Source: https://jsonapi-resources.com/v0.10/guide/resources Demonstrates how to request side-loaded related resources using the 'include' parameter in an HTTP GET request. Specifies the 'Accept' header for JSON API format. ```http GET /articles/1?include=comments HTTP/1.1 Accept: application/vnd.api+json ``` -------------------------------- ### API Response for Created Contact Source: https://jsonapi-resources.com/v0.10/guide/basic_usage An example of the HTTP response received after successfully creating a contact. It includes a 201 Created status and the JSON:API representation of the new contact. ```http HTTP/1.1 201 Created X-Frame-Options: SAMEORIGIN X-Xss-Protection: 1; mode=block X-Content-Type-Options: nosniff Content-Type: application/vnd.api+json Etag: W/"809b88231e24ed1f901240f47278700d" Cache-Control: max-age=0, private, must-revalidate X-Request-Id: e4a991a3-555b-42ac-af1e-f103a1007edc X-Runtime: 0.151446 Server: WEBrick/1.3.1 (Ruby/2.2.2/2015-04-13) Date: Thu, 18 Jun 2015 18:21:21 GMT Content-Length: 363 Connection: Keep-Alive {"data":{"id":"1","type":"contacts","links":{"self":"http://localhost:3000/contacts/1"},"attributes":{"name-first":"John","name-last":"Doe","email":"john.doe@boring.test","twitter":null},"relationships":{"phone-numbers":{"links":{"self":"http://localhost:3000/contacts/1/relationships/phone-numbers","related":"http://localhost:3000/contacts/1/phone-numbers"}}}}} ``` -------------------------------- ### Namespaced Controller Implementation Source: https://jsonapi-resources.com/v0.10/guide/controllers Provides an example of a namespaced controller, `Api::V1::PostsController`, inheriting from `JSONAPI::ResourceController`. This is used in conjunction with namespaced resources to manage API versions. ```ruby module Api module V1 class PostsController < JSONAPI::ResourceController end end end ``` -------------------------------- ### Namespaced Resource Definition (V1) Source: https://jsonapi-resources.com/v0.10/guide/controllers Shows an example of a namespaced `PostResource` within the `Api::V1` module. This version demonstrates how to handle API versioning by modifying resource attributes and relationships compared to a non-namespaced version. ```ruby module Api module V1 class PostResource < JSONAPI::Resource # V1 replaces the non-namespaced resource # V1 no longer supports tags and now calls author 'writer' attribute :title attribute :body attribute :subject has_one :writer, foreign_key: 'author_id' has_one :section has_many :comments, acts_as_set: false def subject @model.title end filters :writer end class WriterResource < JSONAPI::Resource attributes :name, :email model_name 'Person' has_many :posts filter :name end end end ``` -------------------------------- ### Links Configuration Source: https://jsonapi-resources.com/v0.10/guide/resources Manage the generation and exclusion of links for resources and relationships. ```APIDOC ## Links ### Description Controls the generation of links, specifically the default `self` link for resources and links for relationships. Links can be excluded globally or for specific relationships. ### Method Defined within the resource class or relationship options. ### Endpoint N/A (Resource-level configuration) ### Parameters #### Resource Class Methods - **`exclude_links`** (array or symbol) - Excludes links from serialization. Can be an array of link names (e.g., `[:self]`) or a special value (`:default` to exclude default links, `:none` to exclude all links). #### Relationship Options - **`exclude_link`** (array or symbol) - Excludes links for a specific relationship. Similar to `exclude_links`. ### Request Example ```ruby # Exclude the default 'self' link for CityCouncilMeeting resources class CityCouncilMeeting < JSONAPI::Resource attribute :title, :location, :approved exclude_links [:self] # or exclude_links :default end ``` ```ruby class ArticleResource < JSONAPI::Resource has_many :comments # Example of excluding a link for a specific relationship (if applicable) # relationship :comments, exclude_link: [:related] end ``` ### Response #### Success Response (200) Links are included or excluded based on the configuration. #### Response Example (Without `exclude_links [:self]`) ```json { "data": { "type": "city_council_meetings", "id": "...", "links": { "self": "http://example.com/city_council_meetings/1" }, "attributes": { "title": "Meeting Title", "location": "City Hall", "approved": true } } } ``` (With `exclude_links [:self]`) ```json { "data": { "type": "city_council_meetings", "id": "...", "attributes": { "title": "Meeting Title", "location": "City Hall", "approved": true } } } ``` ``` -------------------------------- ### Paginator Configuration Source: https://jsonapi-resources.com/v0.10/guide/resources Configure default pagination settings for all resources or override them at the resource level. ```APIDOC ## Paginator Configuration ### Description Configure default pagination settings for all resources or override them at the resource level. ### Method Configuration via `JSONAPI.configure` block or `paginator` method in resource class. ### Endpoint N/A (Configuration) ### Parameters #### Global Configuration (`JSONAPI.configure`) - **`default_paginator`** (symbol) - Optional - Sets the default paginator. Options: `:none`, `:offset`, `:paged`. - **`default_page_size`** (integer) - Optional - Sets the default page size. - **`maximum_page_size`** (integer) - Optional - Sets the maximum allowed page size. #### Resource-Level Configuration (`paginator` method) - **`paginator`** (symbol) - Optional - Overrides the default paginator for a specific resource. Use `:none` to disable pagination for a resource. ### Request Example ```ruby # config/initializers/jsonapi_resources.rb JSONAPI.configure do |config| config.default_paginator = :offset config.default_page_size = 10 config.maximum_page_size = 20 end ``` ```ruby # app/resources/book_resource.rb class BookResource < JSONAPI::Resource attribute :title attribute :isbn paginator :offset end ``` ### Response N/A (Configuration) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Define Before Create Callback in JSONAPI Resource Source: https://jsonapi-resources.com/v0.10/guide/resources Use `ActiveSupport::Callbacks` to define callbacks for JSONAPI Resources, similar to ActiveRecord. This example shows a `before_create` callback to perform authorization before a resource is created. ```ruby class BaseResource < JSONAPI::Resource before_create :authorize_create def authorize_create # ... end end ``` -------------------------------- ### JSONAPI Configuration Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Configuration options for JSONAPI Resources, including caching and pagination settings. ```APIDOC ## JSONAPI Configuration ### Description Configure JSONAPI Resources behavior, such as enabling caching and setting pagination defaults. ### Method N/A (Configuration file) ### Endpoint `config/initializers/jsonapi_resources.rb` ### Parameters #### Request Body - **config.resource_cache** (object) - Required - Sets the cache store for JSONAPI resources (e.g., `Rails.cache`). - **config.default_caching** (boolean) - Optional - Enables caching for all resources by default (v0.10+). - **config.default_paginator** (string) - Optional - Sets the default pagination strategy (:none, :offset, :paged, or custom). - **config.default_page_size** (integer) - Optional - Sets the default number of records per page. - **config.maximum_page_size** (integer) - Optional - Sets the maximum number of records allowed per page. ### Request Example ```ruby # config/initializers/jsonapi_resources.rb JSONAPI.configure do |config| config.resource_cache = Rails.cache # For v0.10 and later: # config.default_caching = true # Options: :none, :offset, :paged, or a custom paginator name config.default_paginator = :paged # default is :none config.default_page_size = 50 # default is 10 config.maximum_page_size = 100 # default is 20 end ``` ### Response #### Success Response (200) N/A (Configuration changes require application restart) #### Response Example N/A ``` -------------------------------- ### Implement Custom ResourceSerializer with Configuration Description Source: https://jsonapi-resources.com/v0.10/guide/resource_caching This example shows how to create a custom `JSONAPI::ResourceSerializer` that accepts new options. The `config_description` method is overridden to include these new options, ensuring that they are properly considered when determining the serialized value, especially when the options impact the output. ```ruby class MySerializer < JSONAPI::ResourceSerializer def initialize(primary_resource_klass, options = {}) @my_special_option = options.delete(:my_special_option) super end def config_description(resource_klass) super.merge({my_special_option: @my_special_option}) end end ``` -------------------------------- ### Namespaced Routes Configuration Source: https://jsonapi-resources.com/v0.10/guide/controllers Illustrates how to configure routes for namespaced JSONAPI resources using `Rails.application.routes.draw`. This setup allows for versioned APIs by defining routes within nested namespaces. ```ruby Rails.application.routes.draw do jsonapi_resources :posts namespace :api do namespace :v1 do jsonapi_resources :posts end end end ``` -------------------------------- ### Configuring JSON Key Format (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/formatting Demonstrates how to configure the JSON key format for JSONAPI Resources using `JSONAPI.configure`. This example sets the key format to `:camelized_key`, which uses camel casing with an initial lowercase character. ```ruby JSONAPI.configure do |config| # built in key format options are :underscored_key, :camelized_key and :dasherized_key config.json_key_format = :camelized_key end ``` -------------------------------- ### Resource Meta Source: https://jsonapi-resources.com/v0.10/guide/resources Add custom meta information to resource objects. ```APIDOC ## Resource Meta ### Description Allows for the inclusion of custom meta information within each resource object in the API response. This is achieved by defining a `meta` method within the resource class. ### Method Defined within the resource class. ### Endpoint N/A (Resource-level configuration) ### Parameters #### Resource Class Method - **`meta(options)`** - Method to define meta information. It receives an `options` hash. - **`options`** (hash) - Contains: - `:serializer` - The serializer instance. - `:serialization_options` - The contents of the `serialization_options` method on the controller. ### Request Example ```ruby class BookResource < JSONAPI::Resource attribute :title attribute :isbn def meta(options) { copyright: 'API Copyright 2015 - XYZ Corp.', computed_copyright: options[:serialization_options][:copyright], last_updated_at: _model.updated_at } end end ``` ### Response #### Success Response (200) - **`meta`** (object) - An object containing custom meta information for the resource. #### Response Example (Assuming `options[:serialization_options][:copyright]` is 'XYZ Corp.') ```json { "data": { "type": "books", "id": "...", "attributes": { "title": "Example Book", "isbn": "978-3-16-148410-0" }, "meta": { "copyright": "API Copyright 2015 - XYZ Corp.", "computed_copyright": "XYZ Corp.", "last_updated_at": "2023-10-27T10:00:00Z" } } } ``` ``` -------------------------------- ### JSON API Payload with Included Resources Source: https://jsonapi-resources.com/v0.10/guide/resources Example JSON API response payload showcasing side-loaded 'included' resources, typically comments related to an article. Demonstrates the structure for primary data and included related data. ```json { "data": { "type": "articles", "id": "1", "attributes": { "title": "JSON API paints my bikeshed!" }, "links": { "self": "http://example.com/articles/1" }, "relationships": { "comments": { "links": { "self": "http://example.com/articles/1/relationships/comments", "related": "http://example.com/articles/1/comments" }, "data": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] } } }, "included": [{ "type": "comments", "id": "5", "attributes": { "body": "First!" }, "links": { "self": "http://example.com/comments/5" } }, { "type": "comments", "id": "12", "attributes": { "body": "I like XML better" }, "links": { "self": "http://example.com/comments/12" } }] } ``` -------------------------------- ### Complex Filter with :verify and :apply (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/resources An advanced example demonstrating how to use both `:verify` and `:apply` callables for complex filtering. The `:verify` callable converts values to integers, and the `:apply` callable checks for overlap using a PostgreSQL array operator. ```ruby filter :possible_ids, verify: ->(values, context) { values.map {|value| value.to_i} }, apply: ->(records, value, _options) { records.where('possible_ids && ARRAY[?]', value) } ``` -------------------------------- ### Included Relationships (Side-loading) Source: https://jsonapi-resources.com/v0.10/guide/resources Enable side-loading of related resources using the `include` query parameter. ```APIDOC ## Included Relationships (Side-loading Resources) ### Description Support for side-loading related resources via the `include` query parameter. When used, related resources specified in `include` will be returned in the `included` key of the response payload. ### Method GET ### Endpoint `/[resource_path]/{id}?include=[relationship_name]` ### Parameters #### Query Parameters - **`include`** (string) - Optional - Comma-separated list of relationship names to include in the response. - **`fields[resource_type]`** (string) - Optional - Comma-separated list of fields to include for a specific resource type. Important when using `include` to ensure related resources are serialized. ### Request Example ```http GET /articles/1?include=comments HTTP/1.1 Accept: application/vnd.api+json ``` ### Response #### Success Response (200) - **`data`** (object) - The primary resource data. - **`included`** (array) - An array of related resources that were side-loaded. #### Response Example ```json { "data": { "type": "articles", "id": "1", "attributes": { "title": "JSON API paints my bikeshed!" }, "links": { "self": "http://example.com/articles/1" }, "relationships": { "comments": { "links": { "self": "http://example.com/articles/1/relationships/comments", "related": "http://example.com/articles/1/comments" }, "data": [ { "type": "comments", "id": "5" }, { "type": "comments", "id": "12" } ] } } }, "included": [ { "type": "comments", "id": "5", "attributes": { "body": "First!" }, "links": { "self": "http://example.com/comments/5" } }, { "type": "comments", "id": "12", "attributes": { "body": "I like XML better" }, "links": { "self": "http://example.com/comments/12" } } ] } ``` **Note:** When using `include` and `fields` together, ensure that relationships intended for inclusion are also listed in the `fields` parameter (e.g., `fields[posts]=comments,title&include=comments`). ``` -------------------------------- ### Filter Fetchable Attributes in JSONAPI Resource Source: https://jsonapi-resources.com/v0.10/guide/resources Provides an example of overriding the `fetchable_fields` method in a JSONAPI::Resource to conditionally filter attributes. This example prevents guest users from accessing the `email` field. ```ruby class AuthorResource < JSONAPI::Resource attributes :name, :email model_name 'Person' has_many :posts def fetchable_fields if (context[:current_user].guest) super - [:email] else super end end end ``` -------------------------------- ### GET /phone-numbers/:phone_number_id/contact Source: https://jsonapi-resources.com/v0.10/guide/routing Retrieves the 'has_one' related resource for a 'contact' from a 'phone_number'. ```APIDOC ## GET /phone-numbers/:phone_number_id/contact ### Description Retrieves the 'has_one' related resource for a 'contact' from a 'phone_number'. This endpoint is generated when `jsonapi_related_resource :contact` is used within a `jsonapi_resources` block for `phone_numbers`. ### Method GET ### Endpoint `/phone-numbers/:phone_number_id/contact(.:format)` ### Parameters #### Path Parameters - **phone_number_id** (integer) - Required - The ID of the phone number resource. #### Query Parameters None #### Request Body None ### Request Example ``` GET /phone-numbers/1/contact ``` ### Response #### Success Response (200) - **data** (object) - The related contact resource, conforming to JSON:API structure. - **links** (object) - Links related to the resource. #### Response Example ```json { "data": { "type": "contacts", "id": "123", "attributes": { "name": "John Doe" } }, "links": { "self": "/phone-numbers/1/contact" } } ``` ``` -------------------------------- ### GET /contacts Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Retrieves a list of contacts. Without caching or pagination, this can be slow for large datasets. ```APIDOC ## GET /contacts ### Description Retrieves a list of all contacts. This endpoint can be slow with a large number of records if caching and pagination are not configured. ### Method GET ### Endpoint /contacts ### Parameters #### Query Parameters - **page[number]** (integer) - Optional - The page number to retrieve. - **page[size]** (integer) - Optional - The number of records per page. ### Request Example ```bash curl -i -H "Accept: application/vnd.api+json" "http://localhost:3000/contacts" ``` ### Response #### Success Response (200) - **data** (array) - An array of contact objects. - **links** (object) - Contains links for pagination (first, next, last). #### Response Example ```json { "data": [...], "links": { "first": "http://localhost:3000/contacts?page%5Bnumber%5D=1&page%5Bsize%5D=50", "next": "http://localhost:3000/contacts?page%5Bnumber%5D=2&page%5Bsize%5D=50", "last": "http://localhost:3000/contacts?page%5Bnumber%5D=401&page%5Bsize%5D=50" } } ``` ``` -------------------------------- ### Create New Rails Application Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Generates a new Rails application, optionally with PostgreSQL support, skipping JavaScript assets. This is the initial step for setting up the demo app. ```bash rails new peeps --skip-javascript ``` ```bash rails new peeps -d postgresql --skip-javascript ``` -------------------------------- ### Basic ResourceController Implementation Source: https://jsonapi-resources.com/v0.10/guide/controllers Demonstrates the simplest way to implement a controller by inheriting from `JSONAPI::ResourceController`. This provides a fully functional controller out-of-the-box for handling JSONAPI requests. ```ruby class PeopleController < JSONAPI::ResourceController end ``` -------------------------------- ### Adding Related Resources Route Source: https://jsonapi-resources.com/v0.10/guide/routing Configures a nested route to GET all related has_many resources for a given resource. ```APIDOC ## GET /contacts/{contact_id}/phone-numbers ### Description Retrieves all phone numbers related to a specific contact. ### Method GET ### Endpoint /contacts/{contact_id}/phone-numbers ### Parameters #### Path Parameters - **contact_id** (string) - Required - The ID of the contact whose phone numbers are to be retrieved. ### Response #### Success Response (200 OK) - **data** (array) - An array of phone number resources related to the contact. - **type** (string) - The type of the resource (e.g., "phone_numbers"). - **id** (string) - The unique identifier of the phone number. - **attributes** (object) - The attributes of the phone number. #### Response Example ```json { "data": [ { "type": "phone_numbers", "id": "456", "attributes": { "number": "123-456-7890", "type": "mobile" } } ] } ``` ``` -------------------------------- ### Migrate Database Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Runs the database migrations to create the tables for the `contacts` and `phone_numbers` models. This command should be executed after defining the models. ```bash rake db:migrate ``` -------------------------------- ### Configure Development Environment for Eager Loading Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Sets `config.eager_load = true` in `config/environments/development.rb` to ensure all classes are loaded on boot. This is recommended for JSONAPI-Resources to function correctly. ```ruby # Eager load code on boot so JSONAPI-Resources resources are loaded and processed globally config.eager_load = true ``` -------------------------------- ### Query All Contacts via API Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Uses cURL to send a GET request to retrieve a list of all contacts. It specifies the Accept header for JSON:API. ```bash curl -i -H "Accept: application/vnd.api+json" "http://localhost:3000/contacts" ``` -------------------------------- ### Create Resources Directory Source: https://jsonapi-resources.com/v0.10/guide/basic_usage Creates a directory named `resources` inside the `app` directory. This is where the JSONAPI-Resource files will be stored. ```bash mkdir app/resources ``` -------------------------------- ### Initialize JSONAPI Resources Configuration Source: https://jsonapi-resources.com/v0.10/guide/configuration This snippet shows the basic structure for initializing JSONAPI Resources configuration. It creates a configuration block where options can be set. No external dependencies are required beyond the JSONAPI Resources gem itself. ```ruby JSONAPI.configure do |config| end ``` -------------------------------- ### Conditionally Add Custom Links Source: https://jsonapi-resources.com/v0.10/guide/resources Implement conditional logic within the `custom_links` method to include links only when specific criteria are met. This example adds a 'minutes' link only if the meeting is approved. ```ruby class CityCouncilMeeting < JSONAPI::Resource attribute :title, :location, :approved delegate :approved?, to: :model def custom_links(options) extra_links = {} if approved? extra_links[:minutes] = options[:serializer].link_builder.self_link(self) + "/minutes" end extra_links end end ``` -------------------------------- ### Sort by Relationship Field in JSONAPI Resource Source: https://jsonapi-resources.com/v0.10/guide/resources Illustrates how to enable sorting by fields on related resources by overriding `self.sortable_fields`. This example allows sorting `BookResource` by the `name` attribute of its associated `Author`. ```ruby class Book < ActiveRecord::Base belongs_to :author end class Author < ActiveRecord::Base has_many :books end class BookResource < JSONAPI::Resource attributes :title, :body def self.sortable_fields(context) super + [:"author.name"] end end ``` -------------------------------- ### Configure JSONAPI Resources Initializer (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/basic_usage This Ruby code snippet shows how to configure JSONAPI Resources by creating or modifying an initializer file. It sets up basic configuration options for the JSONAPI gem within a Rails application. ```ruby JSONAPI.configure do |config| # Config setting will go here end ``` -------------------------------- ### Prevent Sorting by Attribute in JSONAPI Resource Source: https://jsonapi-resources.com/v0.10/guide/resources Shows how to override the `self.sortable_fields` class method in a JSONAPI::Resource to exclude specific attributes from sorting. This example prevents sorting by the `body` attribute of a `PostResource`. ```ruby class PostResource < JSONAPI::Resource attributes :title, :body def self.sortable_fields(context) super(context) - [:body] end end ``` -------------------------------- ### Customize Base Records for Finders (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/resources Override the `records` class method to customize the base `ActiveRecord::Relation` used by finder methods (`find`, `find_by_key`). This example restricts posts to those belonging to the current user. ```ruby class PostResource < JSONAPI::Resource attributes :title, :body def self.records(options = {}) context = options[:context] context[:current_user].posts end end ``` -------------------------------- ### Configure Default Paginator and Page Sizes in Ruby Source: https://jsonapi-resources.com/v0.10/guide/resources Sets the default paginator and page size for all JSONAPI resources. Supports :none, :offset, and :paged paginators. Configures default and maximum page sizes. ```ruby JSONAPI.configure do |config| # built in paginators are :none, :offset, :paged config.default_paginator = :offset config.default_page_size = 10 config.maximum_page_size = 20 end ``` -------------------------------- ### ResourceControllerMetal Implementation Source: https://jsonapi-resources.com/v0.10/guide/controllers Shows how to use `JSONAPI::ResourceControllerMetal` as a base class for a lighter-weight controller. This option includes only the essential components for `JSONAPI::Resources` integration. ```ruby class PeopleController < JSONAPI::ResourceControllerMetal end ``` -------------------------------- ### Define a Basic JSONAPI Resource Source: https://jsonapi-resources.com/v0.10/guide/resources This snippet shows the fundamental way to define a resource by inheriting from JSONAPI::Resource. It sets up the basic structure for exposing attributes and relationships. ```ruby class ContactResource < JSONAPI::Resource end ``` -------------------------------- ### Customize Relationship Joins with :apply_join (Ruby) Source: https://jsonapi-resources.com/v0.10/guide/resources Customize how relationships are joined by providing an `apply_join` callable. This example augments the default join logic by adding an additional `where` clause to filter authors based on a 'special' context flag. ```ruby class CommentResource < CommentResource has_one :author, class_name: 'Person', apply_join: -> (records, relationship, resource_type, join_type, options) { context = options[:context] records = apply_join(records: records, relationship: relationship, resource_type: resource_type, join_type: join_type, options: options) records.where(author: {special: context.fetch(:special, false)}) } end ```