JSONAPI Resources Anchor

Type Annotation

Prerequisites

Including the Anchor::SchemaSerializable concern adds an optional second argument to JSONAPI::Resource.attribute and JSONAPI::Resource.relationship to enable annotations.

The type signatures of .attribute and .relationship are unchanged otherwise, i.e.

  • if the annotation is included, the options hash becomes the third argument
  • if the annotation is not included, the signatures remain the same

Attributes

In cases where the type of an attribute is not inferable (or incorrectly inferred) you may need to annotate the type.

Example

class UserResource
  attribute :name, Anchor::Types::String
 
  def name
    'static name, actually'
  end
end

name is not inferable because a method was defined on the resource.

See Anchor::Types for all type annotation options.

Exhaustive Example

app/resources/exhaustive_resource.rb
class ExhaustiveResource < JSONAPI::Resource
  include Anchor::SchemaSerializable
 
  class AssertedObject < Types::Object
    property :a, Types::Literal.new("a")
    property "b-dash", Types::Literal.new(1)
    property :c, Types::Maybe.new(Types::String)
    property :d_optional, Types::Maybe.new(Types::String), optional: true
  end
 
  attribute :asserted_string, Types::String, description: "My asserted string."
  attribute :asserted_number, Types::Integer
  attribute :asserted_boolean, Types::Boolean
  attribute :asserted_null, Types::Null
  attribute :asserted_unknown, Types::Unknown
  attribute :asserted_object, AssertedObject
  attribute :asserted_maybe_object, Types::Maybe.new(AssertedObject)
  attribute :asserted_array_record, Types::Array.new(Types::Record.new(Types::Integer))
  attribute :asserted_union, Types::Union.new([Types::String, Types::Float])
  attribute :with_description, Types::String, description: "This is a provided description."
  attribute :inferred_unknown
 
  class LinkSchema < Anchor::Types::Object
    property :self, Anchor::Types::String
    property :some_url, Anchor::Types::String
  end
  anchor_links_schema LinkSchema
 
  class MetaSchema < Anchor::Types::Object
    property :some_count, Anchor::Types::Integer
    property :extra_stuff, Anchor::Types::String
  end
  anchor_meta_schema MetaSchema
 
  def asserted_string = "asserted_string"
 
  def asserted_number = 1
 
  def asserted_boolean = true
 
  def asserted_null = nil
 
  def asserted_unknown = nil
 
  def asserted_object = { a: "a", "b-dash" => 1, c: nil }
 
  def asserted_maybe_object = nil
 
  def asserted_array_record = [{ key: 1 }]
 
  def asserted_union = 2
 
  def inferred_unknown = nil
 
  def resource_overridden = "resource_overridden"
 
  def with_description = "with_description"
end

Relationships

Relationships should generally be inferred correctly, but there still may be cases where you want to override the inferred type.

Example

A belongs_to association is optional but functionally non-null via other methods in your application.

# definitely a contrived example
class Comment < ApplicationRecord
  belongs_to :user, optional: true
  validates :user_id, presence: true
end
 
class CommentResource
  relationship :user, Anchor::Types::Relationship.new(resource: UserResource, null: false)
end

See Anchor::Types::Relationship for all options.

On this page