Handle Creation of Single or Multiple Records in AdonisJS

Support creation of a single record or a group of records using same business logic and in the same controller in AdonisJS.

Typically you create the following controller to handle record creation -

// TodoController.js
async create({ request, auth }) {
    const data = request.all();
    //single record
    return await Todo.create(data);
}

create will happily create a single record as per the input data. What if you want to create multiple records in one go?

The first idea that one may have is to handle everything in the controller. Since the business logic is going to remain the same, and there may be a lot of reuse for auxiliary functions, one is tempted to just do the following.

// TodoController.js
async create({ request, auth }) {
    const data = request.all();
    if (data["data"]) {
      const todoData = await Todo.createMany(data["data"]);
      return todoData;
    } else {
      //single record
      return await Todo.create(data);
    }
}

You can now pass a single record..

{
  "description": "Create Adonis Todo App",
  "date": "2019-01-01",
  "status": "Done"
}

.. or multiple records -

{
  "data": [
    {
      "description": "Create Adonis Todo App",
      "date": "2019-01-01",
      "status": "Done",
      "created_at": "2019-01-01 12:46:09",
      "updated_at": "2019-01-01 12:46:09"
    }
    {
      "description": "Update Todo App",
      "date": "2019-01-01",
      "status": "In Progress",
      "created_at": "2019-01-01 12:52:01",
      "updated_at": "2019-01-01 12:52:01"
    }
  ]
}

Although this works - it may not be the best of the solutions. The problem is that the signature of the request will not remain the same. Since you may also have to return a series of records or a single record, the response is also not consistent.

A better option (arguably) will be to segregate the methods into two and move the reusable parts to a service.

// TodoController.js

const ValidationService = use("App/Services/ValidationService");
// new service that will encompass reusable validation logic

class TodoController {
  async create({ request, auth }) {
    const data = request.all();
    const user = await auth.getUser();

    // reusable logic
    ValidationService.validateUser(data, user);

    return await Todo.create(data);
  }

  async createMultiple({ request, auth }) {
    const data = request.all();
    const user = await auth.getUser();

    // either iterate through individual records here
    // or in the validation service
    ValidationService.validateUser(data, user);

    return await Todo.createMany(data["data"]);
  }
}
comments powered by Disqus