Nested Writes
Nested writes occur via “sideposting”. Using the same example from the
strong resources section, let’s “sidepost” a Person
at the /accounts
endpoint:
# PUT /accounts/123
{
data: {
type: "accounts",
id: "123",
attributes: { name: "updated" }
relationships: {
people: {
data: [
{ id: "1", type: "people", method: "update" }
]
}
}
},
included: [
{
type: "people",
id: "1",
attributes: { name: "updated" }
}
]
}
Here we’ve update the Account
and associated Person
in a single
request. You’ll see this is nothing more than a mirror of a
“sideloading” payload, with one key addition - because HTTP verbs only apply to the top-level resource, we add a method
key for all associated resources. Because we’re sticking to the convention of pairing a Resource with a verb, we call this “REST with Relationships”. Verbs can be one of create
, update
, destroy
or disassociate
.
Read more about the Sideposting Concept
There’s not much code to satisfy this document. Make sure the
relationship is defined in your Resource
:
# app/resources/account_resource.rb
has_many :people,
resource: PersonResource,
foreign_key: :account_id,
scope: -> { Person.all }
And whitelisted in your controller:
# app/controllers/accounts_controller.rb
strong_resource :account do
has_many :people
end
That’s it!
temp-id
There’s one final concept in sideposting, specific to create
. We need
to tell our clients how to update an in-memory object with the
newly-minted id
from the server. To do this, we pass temp-id
(a random uuid) in the
request instead of id
:
# create an Account with a Person in a single request
{
data: {
type "accounts",
attributes: { name: "new account" },
relationships: {
people: {
data: [
{ :'temp-id' => "abc123", type: "people" }
]
}
},
included: [
{
type: "people",
:"temp-id" => "abc123",
attributes: { name: "John Doe" }
}
]
}
Clients like JSORM will handle this for you automatically.