What's New in JSONAPI::Resources

March 12, 2019
web apps, rails, ruby, API, JSON:API

I haven't blogged about JSONAPI::Resources ("JR") since it was introduced over four years ago. Communication on our blog has unfortunately taken a backseat to many other objectives, including new features for JR, work on a soon-to-be-released product (why we started this in the first place), and consulting to keep the lights on. However, I'd like to get back to communicating here on a more regular basis.

Growth and maturity

Since JR's introduction both its capabilities and its community have grown substantially. Support for the major features of the JSON:API spec has been added over many releases. Customizing the behavior of resources has become cleaner. Adding callables to individual filters, sorts, and soon relationships has replaced overriding the core methods of the library, which has improved the clarity of code that defines resources. Another huge win was the addition of caching support in v0.9, which can make a big difference in performance for frequently requested resources. And, perhaps most importantly for me personally, JR is working well as the foundation for the backend of the product we're building.

New core team members

Sean Devine joined JR's core team in the very early days of the project. Sean's a long time contributor who's used JR to help build his construction logistics business, XBE.

Scott González just recently joined the core team. If you've ever had a question in our Gitter community, chances are that Scott was there to help you out. I'm really grateful to have Scott on the core team to help the project at a whole other level.

Improved documentation

We've added a documentation site where you can get updated on all the features that are now in the project. A Gitter community has been setup for chat and support. There you can usually get an answer quickly as there are multiple people watching the conversations and willing help out.

v0.10.0 is right around the corner

JR is now up to stable v0.9.5, with v0.10 currently in beta. Now seems like a good time to discuss what's coming in the v0.10 release and beyond.

Resource finders

The JSONAPI::Resource class was originally conceived as a thin layer on top of ActiveRecord models. JSONAPI::Resource would proxy down to the model for attributes, compose ActiveRecord::Relation expressions for resource searching and joins between resources over defined relationships. Some of the logic for how to perform these tasks was specific to models based on a SQL database which could use ActiveRecord::Relation. This resulted in a lot of ActiveRecord::Relation code in the JSONAPI::Resource class, which makes it difficult to back resources with ORMs other than ActiveRecord.

In v0.10 the functionality that interacts with the data stores has been abstracted into modules called resource finders. Resource finders work with the Processor to support finding resources while applying all the requested sorting, filtering, joining, and pagination.

ActiveRelationResourceFinder

As of this writing the only resource finder is the ActiveRelationResourceFinder. This is not a simply an extraction of the old resource code, but rather reworks the methods used to find resources and the related resources for a request. This resource finder approaches the finding of resources in several phases. The first phase searches for the identities and cache fields using pluck. This results in a very fast query to the database without instantiating model instances. When included resources are requested their identities are also found and added to a ResourceSet. The next phase, optionally, looks for already serialized resources from the cache and adds them to the resource set, avoiding instantiation and serialization of those models. Finally all remaining models are loaded by identity and serialized. By breaking the process into phases we gain efficiencies when communicating in bulk with the cache and with the database for each resource type, as well as minimizing model instantiation and serialization.

What's left for the beta period?

There's still a bit more to do before v0.10 is out of beta. Since support for additional resource finders is planned, we should allow resources with relationships to other resources that use different resource finders. For example, these relationships might reference a remote API server or even resources stored in a document database. A few changes to the existing codebase will be needed to make this possible.

What's next after v0.10.0? Sponsor a feature 🚀

Cerebris, which consists of just Dan and myself, has been self-funding the bulk of the development of JSONAPI::Resources since its inception. As you can probably imagine, this has been quite an undertaking for a two person firm, even with all the help from the other contributors (for which we are very grateful!). Frankly, we could use your help. It would be much appreciated if companies that are using JR could help out by sponsoring the development of new features. This would allow us to focus on the JSONAPI::Resources instead of consulting on completely separate projects. By allowing us to focus on this gem, you and the rest of the community can get useful new features more quickly, and you can focus on writing your own applications using JR.

We're still deciding what's coming next. Honestly, many of our decisions will depend upon funding. These are the features we're considering for upcoming releases:

Multiple operations

Supporting multiple operations per request is one of the most frequently requested features. Adding support for this in JR will first require finalizing support in the JSON:API spec. As one of the primary authors of the JSON:API spec, Dan is involved with shepherding the addition of multiple operation support into JSON:API. Once the feature is finalized in the spec, support can be added to JSONAPI::Resources. The exact details required are TBD based on the final form of the spec. However the foundations of JR were designed with multiple operations in mind.

Expanded filter types

JSONAPI::Resources supports basic filtering on relationships by ids and text filters with an exact match for fields. Custom filters can be used, but those require custom programming by the API authors. Built in support for common filtering concepts would be a big improvement.

For example making a text search case insensitive:

1
2
3
4
class PostResource < JSONAPI::Resource
  attribute :title
  filter :title, case: :insensitive
end

Currently this requires a custom apply callable.

Profiles

Profiles have been added to JSON:API v1.1. Support for profiles in JSONAPI::Resources will require possibly significant changes. Beyond the obvious support for declaring and negotiating profiles, JR will also need to allow building custom profiles with unique capabilities. One example of this would be to allow the installation of different filtering profiles.

More resource finders

As alluded to above, JR could be extended to support additional resource finders. A prime candidate is a resource finder to support document databases such as MongoDB. Another possibility is a resource finder that proxies to another JSON:API server.

Custom features

If you have a custom feature in mind, please get in touch. As long as it's compliant with the JSON:API spec, we'll probably be glad to work with you to add support directly to JR. We're also open to working with you to build custom solutions that utilize JSONAPI::Resources to solve your business-specific needs.