A library for creating models from API endpoints.
Imagine an API endpoint that looks like this
# http://www.example.com/blogs/1
{
blog: {
id: 1,
name: "A blog",
links: {
posts: "/posts?blog_id=1"
}
}
}
RubyJsonApiClient allows you to write
class Blog < RubyJsonApiClient::Base
field :name
has_many :posts
end
Blog.find(1).name
# => "A blog"
Blog.find(1).posts.map(&:title)
# => ["Rails is Omakase"]
It has multiple API adapters so working with any serialization format is easy.
- Active Model Serializers
Add this line to your application's Gemfile:
gem 'ruby_json_api_client'
And then execute:
$ bundle
The first thing that needs to be done is creating an adapter and serializer. It is recommended you use one of the adapters that ships with this gem.
For this example, we will setup an adapter that reads from ActiveModelSerializers based APIs.
# config/initializers/ruby_json_api_client.rb
# Setup the AMS adapter to pull from https://www.example.com
RubyJsonApiClient::Store.register_adapter(:ams, {
hostname: 'www.example.com',
secure: true
});
# Use AMS based serializer
RubyJsonApiClient::Store.register_serializer(:ams)
# Default all models to AMS
RubyJsonApiClient::Store.default(:ams)
Now you can setup your classes based on your API endpoints.
class Book < RubyJsonApiClient::Base
field :title
has_one :author
end
Book.all
# => Loads collection from https://www.example.com/books
Book.query(type: 'fiction')
# => Loads collection from https://www.example.com/books?type=fiction
Book.find(1)
# => Loads model from https://www.example.com/books/1
Most relationships rules are defined based on the semantics of the adapter you choose. For example, when using Active Model Serializers relationships are mostly likely going to be sideloaded or accessed by links.
class Book < RubyJsonApiClient::Base
field :title
has_one :author
end
class Author < RubyJsonApiClient::Base
field :name
has_many :books
end
With an AMS API that sideloads relationships, such as:
# http://www.example.com/books
{
books: [{
id: 1,
title: "Example book",
author_id: 123
}],
authors: [{
id: 123,
name: "Test author"
book_ids: [1]
}]
}
We could do the following.
Book.find(1).author.name
# => "Test author"
Author.find(123).books
# => [Book(<id: 1>)]
There are many more ways to load relationship data. You should consult the adapter guide based on which adapter you are using.
- Per model serializers and adapters (Store#adapter_for_class)
- Store#find_many_relationship should return reloadable proxy
- Store#find_single_relationship should return reloadable proxy
- Write AMS adapter docs
- Write docs for custom adapter
- Auto figure out default serializer from registered adapter(s)
- has one should accept field_id = 123. Post.find(1).author_id = 5
- Adapter/serializer should be able to add methods to models (author_id=)
- Faraday follow redirectos
- Faraday cache
- REST handle 4xx errors
- serializer: json to model rename data to model