Giter VIP home page Giter VIP logo

jsonapi_parameters's Introduction

JsonApi::Parameters

Simple JSON:API compliant parameters translator.

Gem Version Maintainability Test Coverage CircleCI

Documentation

Usage

Installation

Add this line to your application's Gemfile:

gem 'jsonapi_parameters'

And then execute:

$ bundle

Or install it yourself as:

$ gem install jsonapi_parameters

Rails

Usually your strong parameters in controller are invoked this way:

def create
  model = Model.new(create_params)

  if model.save
    ...
  else
    head 500
  end
end

private

def create_params
  params.require(:model).permit(:name)
end

With jsonapi_parameters, the difference is just the params:

def create_params
  params.from_jsonapi.require(:model).permit(:name)
end

Relationships

JsonApi::Parameters supports ActiveRecord relationship parameters, including nested attributes.

Relationship parameters are being read from two optional trees:

  • relationships,
  • included

If you provide any related resources in the relationships table, this gem will also look for corresponding, included resources and their attributes. Thanks to that this gem supports nested attributes, and will try to translate these included resources and pass them along.

For more examples take a look at Relationships in the wiki documentation.

Client generated IDs

You can specify client_id_prefix:

JsonApi::Parameters.client_id_prefix = 'client_'

Default client_id_prefix is cid_

All IDs starting with JsonApi::Parameters.client_id_prefix will be removed from params.

In case of creating new nested resources, client will need to generate IDs sent in relationships and included parts of request.

{
  "type": "multitracks",
  "attributes": {
    "title": "Multitrack"
  },
  "relationships": {
    "tracks": {
       "data": [
        {
          "type": "tracks",
          "id": "cid_new_track"                 // Client ID for new resources -> needs to match ID in included below
        }
       ]
    }
  },
  "included": [
    {
      "id": "cid_new_track",                    // Client ID for new resources -> needs to match ID in relationships below
      "type": "tracks",
      "attributes": {
        "name": "Drums"
       }
    }
  ]
}
params.from_jsonapi

{
  "multitrack" => {
    "title" => "Multitrack",
    "tracks_attributes" => {
      "0" =>  {                                 // No ID is present, so ActiveRecord#create correctly creates the new instance
         "name" => "Drums"
      }
    }
  }
}

In case of updating existing nested resources and creating new ones in the same request, client needs to generate IDs for new resources and use existing ones for existing resources. Client IDs will be removed from params.

{
  "type": "multitracks",
  "attributes": {
    "title": "Multitrack"
  },
  "relationships": {
    "tracks": {
       "data": [
        {
          "type": "tracks",
          "id": "123"                           // Existing ID for existing resources
        },
        {
          "type": "tracks",
          "id": "cid_new_track"                 // Client ID for new resources -> needs to match ID in included below
        }
       ]
    }
  },
  "included": [
    {
      "id": "123",                              // Existing ID for existing resources
      "type": "tracks",
      "attributes": {
        "name": "Piano"
       }
    },
    {
      "id": "cid_new_track",                    // Client ID for new resources -> needs to match ID in relationships below
      "type": "tracks",
      "attributes": {
        "name": "Drums"
       }
    }
  ]
}
params.from_jsonapi

{
  "multitrack" => {
    "title" => "Multitrack",
    "tracks_attributes" => {
      "0" =>  {
         "id" => "123",
         "name" => "Piano"
      },
      "1" =>  {                                 // No ID is present, so ActiveRecord#update correctly creates the new instance
         "name" => "Drums"
      }
    }
  }
}

Translate

Plain Ruby / outside Rails

params = { # JSON:API compliant parameters here
	# ...
}

class Translator
  include JsonApi::Parameters
end
translator = Translator.new

translator.jsonapify(params)

Mime Type

As stated in the JSON:API specification correct mime type for JSON:API input should be application/vnd.api+json.

This gem's intention is to make input consumption as easy as possible. Hence, it registers this mime type for you.

Stack limit

In theory, any payload may consist of infinite amount of relationships (and so each relationship may have its own, included, infinite amount of nested relationships). Because of that, it is a potential vector of attack.

For this reason we have introduced a default limit of stack levels that JsonApi::Parameters will go down through while parsing the payloads.

This default limit is 3, and can be overwritten by specifying the custom limit.

Ruby

class Translator
    include JsonApi::Parameters
end

translator = Translator.new

translator.jsonapify(custom_stack_limit: 4)

# OR

translator.stack_limit = 4
translator.jsonapify.(...)

Rails

def create_params
    params.from_jsonapi(custom_stack_limit: 4).require(:user).permit(
        entities_attributes: { subentities_attributes: { ... } }
    )
end

# OR

def create_params
    params.stack_level = 4

    params.from_jsonapi.require(:user).permit(entities_attributes: { subentities_attributes: { ... } })
ensure
    params.reset_stack_limit!
end

Customization

If you need custom relationship handling (for instance, if you have a relationship named scissors that is plural, but it actually is a single entity), you can use Handlers to define appropriate behaviour.

Read more at Relationship Handlers.

Team

Project started by Jasiek Matusz.

Currently, jsonapi_parameters is maintained by Visuality's Open Source Commitee.

License

The gem is available as open source under the terms of the MIT License.

jsonapi_parameters's People

Contributors

marahin avatar nikajukic avatar batshoes avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.