Understanding how strapi relations works

Ayeye Brazo picture Ayeye Brazo · May 10, 2019 · Viewed 7.4k times · Source

I'm new to strapi and in general with back end development and I'm trying to understand how a very small things should work.

I have a User model, a Profile model and a Fare model.

A User can have a Profile so I created a relation has and belongs to one. A Profile can have a Fare and I created the same relation between Profile and Fare.

What I noticed here is:

When in the client I land to the profile section I do save it with all it properties like: name, surname, address, etc... and everything is going fine by adding the user id to it.

The point here is that in the same profile section I also have fares inputs and what I would like to do is to save fares by saving the profile and not adding a special save button just for the fares...

Is it something possible to do or am I doing something wrong in here?

I'm separating fares by profile to be able to better find, organise and work with fares without querying for profiles every time but having profile records by id ro something...

Can someone explain clearly the best approach and what should I do to achieve it correctly? Thanks

Answer

Fabrizio Bertoglio picture Fabrizio Bertoglio · May 20, 2019

The Form

HTML input to create nested json data you can build a form and test the output

<form action="profiles" method="POST" accept-charset="utf-8">
  <input type="text" name="name" value="MyProfileName" />
  <input type="text" name="fare[name]" value="MyProfileFareName" />
</form>

Parsing the parameters

Parameters will be received from your backend as

name=MyProfileName&fare[name]=MyProfileFareName

The controller will parse the above parameters as json

{
  'profile' => {
    'name' => 'MyProfileName',
    'fare' => {
        'name' => 'MyProfileFareName',
    }
  }
}

The controller create or update action

Controller should be responsible to use the parameters received and update the Database Models. The add and edit methods to persist the model in the database are defined inside the services objects (not inside the controller), the controller responsibility is solely to call those methods.

You can retrieve the parameters from the body of the request. The request object is available inside the controller ctx.request

As in this example the create action uses the .add method from the category services class. The api docs have no explanation about this and you should follow the example on github.

module.exports = {
  // POST /profiles
  create: async (ctx) => {
    // use the fare service to add a new entry with value request.body.fare
    var profile = strapi.services.profile.add(ctx.request.body)
    strapi.services.fare.add(ctx.request.body.fare)
    return profile 
  }
};

The Profile service add and edit methods

you can review the examples on github to better understand the logic of the add and edit methods.

add: async (values) => {
    // Extract values related to relational data.
    const relations = _.pick(values, Profile.associations.map(ast => ast.alias));
    const data = _.omit(values, Profile.associations.map(ast => ast.alias));

    // Create entry with no-relational data.
    const entry = await Profile.create(data);

    // Create relational data and return the entry.
    return Profile.updateRelations({ _id: entry.id, values: relations });
},