Skip to content

Presentation of API v2 Overview

Harriet Craven edited this page Feb 4, 2025 · 1 revision

Sequencescape

Key concepts of the API

  • Controllers manage the entry point for methods used for a response and generate operations to complete for the request as seen in QcAssaysController.
  • Resources define how resources should present themselves, which values they can accept when being created or updated and how to get values in and out of the models, as seen in TransferResource.
  • OperationProcessors work alongside the controller to perform the actions given in the request. These give us a way to perform non-standard operations for a request as seen in QcFileProcessor.
  • Routing is similar to standard Rails, but uses the special jsonapi_resources keyword, like in the routes.rb file.

How pluralisation works

Controllers use the plural form, but processors and resources use the singular. Definition of the pluralisation of complicated words like Labware or Person/People are defined in the inflections.rb file.

Look at the endpoints working

Look at basic endpoint usage

  • Getting all resources of a type.
  • Filtering resources.
  • Including relationships.
  • Creating new resources.

Look at error reporting

  • Missing required parameter.
  • Unrecognised parameters.
  • Custom errors like bad combinations of parameters for TagLayoutResource.

How permissions are defined

Permissions for resources

  • immutable anywhere in the resource ensures that only the GET method work on the endpoint. See TransferRequestResource.
  • jsonapi_resources can be marked to disallow specific actions, or to only allow a list of actions. See TagLayouts in the routes.rb file.

Permissions for attributes and relationships

Permissions about which fields can be fetched, created or updated is defined by methods on the resource.

  • fetchable_field()
  • self.updatable_fields(context)
  • self.creatable_fields(context)

The default implementations return the symbols for all the fields, but we have overrides in the BaseResource class which populate them using properties on the fields.

  • readonly: true
  • write_once: true
  • writeonly: true

Edge cases

always_include_linkage_data

Set this property to true on a field to always be given the "type" and "id" of the related object, even if it hasn't been requested to be included. See RequestResource for an example of this being used.

Beware how the gem used by Limber interprets this result. It's only useful if you don't intend to get the rest of the data for the related resource.

Custom methods

You can declare custom methods, but you must parse the incoming request yourself and respond with a JSON:API compliant response, without help from the gem. This is necessary if you want to create endpoints like the preview one on BaitLibraryLayoutsController though.

Documentation considerations

Documentation is written using YARD docs. This is focussed mainly on the resources and we should try to follow some of the patterns already used. See QcFileResource for a comprehensively documented resource.

  • Classes should document what the resource is used for, how to call its endpoint, what the permissions are like for the resource and links to JSON:API documentation.
  • Attributes should use the @!attribute YARD directive, indicating the permissions for the attribute, the return type and a good description of what the attribute is used for.
  • Relationships should be documented similarly to attributes. In some legacy resources, there is both an attribute and a relationship for a related item. See BaitLibraryLayoutResource for an example. In these cases, the attribute should be marked as deprecated and should yield to values passed by the relationship. The attribute should also not be fetchable.
  • Filters should use the @!method YARD directive, should list what the intention of the filter is and should give an example of the request you might want to use to apply the filter.

The documentation is available on GitHub pages and can be updated when we want using a pipeline.

Unit testing

Custom matchers for resources

We have test matchers for resources that can test the model name for a resource, the behaviour of attributes, the behaviour of relationships and whether a filter has been defined. See QcFileResource specs for an example of many of these. The below are examples of the sort of thing available.

  • Model name
    • have_model_name
  • Attributes
    • have_readonly_attribute
    • have_write_once_attribute
    • have_writeonly_attribute
  • Relationships
    • have_a_readonly_has_one
    • have_a_write_once_has_one
    • have_a_readonly_has_many
    • have_a_write_once_have_many
    • These can all be chained with with_class_name
  • Filters
    • filter

Coverage for requests

Requests should cover a range of tests on how the resource can be manipulated via the API. The Plates spec gives a good overview of the sorts of tests you might want to perform. These are usually a bit specific to the resource, but try to follow a standard pattern like the following.

  • Confirm API authentication applies to the endpoint.
  • Create a number of the resource.
    • Can you get all of them back via the base endpoint with a GET request?
  • Create a single instance of the resource.
    • When you get the single instance back, are all the expected fields there?
    • Do the fields contain the correct values?
    • Are the write-only fields missing like they should be?
    • Are relationships in the response?
    • If you ask for them, are the related resources included in the response?
  • Attempt to PATCH an existing resource.
    • Is the endpoint blocked when it should be?
    • If not blocked, is the model updated?
    • If not blocked, is the response representative of the updated resource?
  • Attempt to POST a new resource.
    • If the endpoint should be blocked, is it?
    • Has the model record been created?
    • Is the response representative of the created model?
    • Have related resources had their model records associated with the new resource?
    • Are read-only fields generating an error when included in the request?
    • Are any custom handling of requests generating the appropriate errors?

Limber

TBC