Skip to content

Relationship handlers

Jasiek Matusz edited this page Dec 6, 2019 · 2 revisions

jsonapi_parameters tries to assume the type of relationship by the structure data tree is.

For instance:

{
    data: {
        type: 'movies',
        attributes: {
          title: 'The Terminator',
        },
        relationships: {
          director: {
            data: {
              id: 682, type: 'directors'
            }
          }
        }
    }
}

relationships.director.data is a Hash, and so JsonApi::Parameters will assume that it is a to-one relationship.

In contrary, for has_many relationship:

{
    data: {
        type: 'movies',
        attributes: {
          title: 'The Terminator',
        },
        relationships: {
          genres: {
            data: [{
              id: 1, type: 'genres'
            },
            {
              id: 2, type: 'genres'
            }]
          }
        }
    }
}

relationships.genres.data is an Array, so it is assumed to be a to-many relationship.

There are edge cases however. One example would be scissors. It can be a to-one relationship, and in this case, it will need some special treatment.

If you would like to remove such a relationship, jsonapi_parameters will not allow you to do it - because to-many relationships cannot be nullified (instead, JSON:API urges you to pass an empty array as a call to "empty" the relationship). But scissors is not a to-many relationship, it is 1-1 relationship - what can we do then? We have to define a custom handler that will tell JsonApi::Parameters specifically what to do with this relationship.

In order to do it, you need to first register a handler:

JsonApi::Parameters::Handlers.add_handler(:handle_plural_nil_as_belongs_to_nil, scissors_handler)

then you need to register relationship handler:

JsonApi::Parameters::Handlers.set_resource_handler(:scissors, :handle_plural_nil_as_belongs_to_nil)

and you're set. Now, if you try this:

{
  data: {
    type: 'users',
    id: '666',
      attributes: {
        first_name: 'John'
      },
      relationships: {
        scissors: { data: nil }
      }
    }
  }
}

JsonApi::Parameters will return this:

user: { first_name: 'John', id: '666', scissors_id: nil }

Obviously this example is just a very trivial one, and will help us only if we ever want to empty the relationship. Usually the handlers you register will need to contain proper logic that checks what kind of value does the relationship yield, and based on that do some action.

Requirements

Arguments

Handlers ARE ALWAYS passed three arguments: relationship_key, relationship_value and jsonapi_included which is an Array that represents the included tree in the JSON:API input format. It is especially useful in cases when you want nested attributes to be also passed.

Return value

Handlers HAVE TO return an Array of two objects: (string) relationship key, and (object) relationship value.

Clone this wiki locally