So let's say we have three simple resources: Groups, Users, and GroupUsers.
Groups - Represent interest groups which can be subscribed by users.
{
name: 'Colorado Mountain Biking Group'
ownerId: 1 (Some user)
}
GroupUsers - Represents the junction table in the many to many Groups - Users relationship. Group membership status and some other attributes are stored here.
{
userId: 2,
courseId: 1,
color: '#FFFFFF',
nickname: 'MBG Colorado',
status: 'accepted'
}
Since our API client will always handle the group from the perspective of the authenticated user, GET /api/groups/1 AUTH(userId=2)
should return:
Group (Includes GroupUser for authenticated user)
{
id: 1
name: 'Colorado Mountain Biking Group'
ownerId: 1,
groupUser: {
userId: 2,
courseId: 1,
color: '#FFFFFF',
nickname: 'MBG Colorado',
status: 'accepted'
}
}
Someone suggested to me that our API Clients should not know or care about the junction table, all they should care about is the group, so I should instead respond with a merged resource like so:
group (In reality group merged with groupUsers for the authenticated user.)
{
id: 1
name: 'Colorado Mountain Biking Group'
ownerId: 1,
userId: 2,
color: '#FFFFFF',
nickname: 'MBG Colorado',
status: 'accepted'
}
The problem I see with this (besides merging issues like repeated Id's and createdAt/updatedAt timestamps)is that the API clients will then use this same resource to further interact with our API endpoints.
If an API client wishes to update the groupUser resource he would:
PUT /api/groups/1
{
id: 1
name: 'Colorado Mountain Biking Group'
ownerId: 1,
userId: 2,
color: '#000000',
nickname: 'Some other value',
status: 'accepted'
}
So now we would also need to scan request bodies and differentiate between group and groupUser attributes. Is the hassle worth it? Even when API consumers are other in-house developers?
Groups
andGroupUsers
in the samePUT
request? Can you think of a use case where the same action requires updating both the group's name and some user's status in that group?