Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manage relationship between 3 resources in REST API

I'm creating an API based on REST concept but I'm still a bit confused talking about relating resources.

I've a website where people can signup in multiple groups and choose multiple roles. For example let's take people that signup in companies as scenario:

Companies

  1. Facebook
  2. Google
  3. Apple

Roles

  • Marketing
  • Sales
  • Development
  • Customer support

So, when I want to create a user in a new company with certain roles, I would pass something like this into a POST request to /users endpoint

{
       "username" : "raffaele.izzia",
        "email"   : "[email protected]",
        "groups"  : [{
          "id" : 1,
          "roles" : ["Sales","Customer support"]
        },
        {
          "id" : 2,
          "roles" : ["Sales","Marketing"]
        }]
}

With this approach, once I get some users from the API I always know in which groups/roles they are.

But what about requests on /groups endpoint?

If I GET /groups/google I should receive info about users/roles too. So it could be something like this

{ 
    groups: [{
        "id" : 2,
        "name"   : "Google",
        "users"  : [2,3,4,10,35,50] //role will be included in the single resource once you expand this collection
    }]
}

or maybe this:

{ 
    groups: [{
        "id" : 2,
        "name"   : "Google",
        "roles"  : [{
           "name"  : "Sales"
           "users" : [2,3,4,10]
        },{
           "name"  : "Marketing"
           "users" : [4,10,8,57]
        }]
    }]
}

What do you think is the best solution for this kind of relationships?

like image 371
Raffaele Izzia Avatar asked Mar 19 '14 07:03

Raffaele Izzia


1 Answers

This is a good question. Definitely a tricky situation.

I think the typical RESTful answer would be to think in terms of nouns, AKA resources. Even though you view this 3-way connection as a relationship between nouns, the connection itself is a noun. That's what you want your REST API to expose.

For lack of a better term, perhaps the name for your connection is an assignment (or an allocation, or whatever). E.g. "Alice working for Google in Marketing" is an assignment.

This now opens up new possibilities that should get you what you need.

E.g. an assignment object:

{
    "id": "...",
    "user": {...},  // e.g. Alice
    "group": {...}, // e.g. Google
    "role": "Marketing"
}

And fetching /users/alice/assignments returns a list of all of her assignments.

Similarly, fetching /groups/google/assignments returns a list of all the assignment objects for people working at Google.

The advantage to this is that now your assignments are truly first-class. You can now do things like keep track of old assignments, while having your main APIs return only current ones. Etc. (Props to this answer for inspiration here.)

Hope this helps!

like image 113
Aseem Kishore Avatar answered Oct 29 '22 17:10

Aseem Kishore