koala
koala

Reputation: 1564

Loopback.io belongsTo in REST

I'm a bit confused about the belongsTo relation function of loopback.io

So let's take the following example:

I have a model called Project which has a relation to a Customer object. So a Project belongs to a Customer.

This is my Project model

{
  "name": "Project",
  "plural": "Projects",
  "base": "PersistedModel",
  "strict": false,
  "idInjection": false,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "title": {
      "type": "string",
      "required": true
    },
    "description": {
      "type": "string"
    },
    "dateCreated": {
      "type": "date"
    }
  },
  "validations": [],
  "relations": {
    "customer": {
      "type": "belongsTo",
      "model": "Customer",
      "foreignKey": "customerId"
    }
  },
  "acls": [],
  "methods": {}
}

So when I run the app and I go to http://0.0.0.0:3000/explorer I can see the API. But When I go to project I only see

 GET /Projects/{id}/customer     Fetches belongsTo relation customer.

I was also expecting other functions like

 POST /Projects/{id}/customer 
 DELETE /Projects/{id}/customer 

Why are they not available here? Or how can I set the customer for a project via REST API?

Upvotes: 1

Views: 1406

Answers (3)

xangy
xangy

Reputation: 1205

Let's first understand belongsTo relationship, to understand why only GET rest endpoint is created:

GET /Projects/{id}/customer     Fetches belongsTo relation customer.

And why Loopback didn't created the below links:

POST /Projects/{id}/customer 
DELETE /Projects/{id}/customer

belongsTo relationship creates a one-to-one relation between two model instance. It is used to provide ownership of one instance to another instance. In your case, project model instance belongs to a customer model instance. Now since project belongs to customer, therefore customer owns the project instance and so explanation for the rest endpoints.

GET /Projects/{id}/customer     Fetches belongsTo relation customer.

since customer can have project instance, therefore above is valid as customers can be fetched for projects.

POST /Projects/{id}/customer
DELETE /Projects/{id}/customer

since customer don't belong to a project rather has project, above rest endpoints doesn't make sense as projects creating or disowning its owner(customer).

Upvotes: 3

achintverma
achintverma

Reputation: 186

first your Project model is missing the customerId field which you mentioned for the belongsTo relation.

Here's Project Model

{
  "name": "Project",
  "plural": "Projects",
  "base": "PersistedModel",
  "strict": false,
  "idInjection": false,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "title": {
      "type": "string",
      "required": true
    },
    "description": {
      "type": "string"
    },
    "dateCreated": {
      "type": "date"
    },
    "customerId": {
      "type": "string",
      "required":true
  },
  "validations": [],
  "relations": {
    "customer": {
      "type": "belongsTo",
      "model": "Customer",
      "foreignKey": "customerId"
    }
  },
  "acls": [],
  "methods": {}
}

Now your Customer model should also have other part of the relationship hasMany. Without that it won't work as expected.

Here's code for Customer model

{
  "name": "Customer",
  "plural": "Customers",
  "base": "PersistedModel",
  "strict": false,
  "idInjection": false,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "name": {
      "type": "string",
      "required": true
    },
    "email": {
      "type": "string",
      "required": true
    },
    "dateCreated": {
      "type": "date"
    }
  },
  "validations": [],
  "relations": {
    "projects": {
      "type": "hasMany",
      "model": "Project",
      "foreignKey": "customerId"
    }
  },
  "acls": [],
  "methods": {}
}

Now with both sides of relationship from Customer <-> Project is defined, your API should have endpoints like:

GET Customers/{id}/Projects
POST Customers/{id}/Projects
PUT Customers/{id}/Projects

Endpoints you mentioned are not valid since you can not create Customers for Project but other way around.

Upvotes: 2

Mattheleon
Mattheleon

Reputation: 1

It does not work like that as far as I know. In order to create the link you need to create the Customer and then use the id for that customer as the id in the Project model.

So your API calls would be:

POST /Customer

to create the Customer, followed by

POST /Project

to create the Project.

In the second post you would need to specify the the CustomerId to link the Project to the customer or you would need to update the Project with the customerId after the fact.

then:

Projects/{id}/customer

to retrieve the customer belonging to the Project.

Or you can write your own remote method on one of the models to perform this in one call.

The complete list of relation APIs can be found here:

StrongLoop Relations API

Upvotes: 0

Related Questions