Axway Appcelerator Blog

The Leading Resource for All Things Mobile

Arrow Composite Model POST

13 Flares 13 Flares ×

Currently in Arrow Builder, create (e.g. POST), is not supported for Composite models. However, using a pre-block we can support the POST (and UPDATE) request and implement any transaction logic required.

Take an employee model:


var Arrow = require('arrow');
var Model = Arrow.createModel('employee', {
	fields: {
		fname: {
			type: String
		},
		lname: {
			type: String
		}
	},
	connector: 'appc.arrowdb',
	actions: [
		'create',
		'read',
		'update',
		'delete',
		'deleteAll'
	]
});
module.exports = Model;

and a vacation model:


var Arrow = require('arrow');
var Model = Arrow.createModel('vacation', {
	fields: {
		eid: {
			type: String
		},
		count: {
			type: Number
		}
	},
	connector: 'appc.arrowdb',
	actions: [
		'create',
		'read',
		'update',
		'delete',
		'deleteAll'
	]
});
module.exports = Model;

and a composite model join of the two, called, employeeAndVacation:


var Arrow = require('arrow');
var Model = Arrow.createModel('employeeAndVacation', {
	fields: {
		fname: {
			model: 'employee',
			type: String
		},
		lname: {
			model: 'employee',
			type: String
		},
		count: {
			model: 'vacation',
			type: Number
		}
	},
	connector: 'appc.composite',
	actions: [
		'create',
		'read',
		'update',
		'delete',
		'deleteAll'
	],
	metadata: {
		left_join: [
			{
				model: 'vacation',
				join_properties: {
					eid: 'id'
				}
			}
		]
	}
});
module.exports = Model;

This is visually described below:

arrow-composite-1

I would like to use these models to store a list of employees and a list of vacation days for each employee. The eid field in the vacation model links to the employee model. The composite employeeAndVacation model joins the two so that I can view employee names and their vacation days together.

Currently, Arrow will return an error if I try to POST to this composite model directly to populate the fields of both models:

arrow-composite-2

Certainly, I can call the employee and vacation models separately but I would like to use Arrow and the composite employeeAndVacation model to encapsulate any transaction logic in creating and updating these models. In this example, the transaction logic is simple for a create:

  1. create an employee entry
  2. populate the new employee entry with the first and last name
  3. retrieve the id of the newly created employee
  4. create a new vacation entry
  5. populate the vacation entry with the number of vacation days for that employee and the id of the employee

‘createEmployee’ Block

I will use a pre block to help me here. The idea is to add a pre-block to the composite model that only gets executed on a POST and then it will return the proper response and block the remainder of the Arrow API flow (since it will error on a POST to a composite model for joined fields).

The first thing I need to do is define a block and run it when there is a POST (i.e. create).

I will create a pre-block, createEmployee, that implements the above transaction logic, as follows:


var Arrow = require('arrow');
var PostBlock = Arrow.Block.extend({
	name: 'createEmployee',
	description: 'create a new employee and linked vacation entry',
	action: function (req, resp, next) {
		if(!req.body.fname || !req.body.lname || !req.body.count) {
			errorReply("fname AND lname AND count required, please try again");
		} else {
			var employee = Arrow.getModel("employee");
			var employeeObject = {
				fname: req.body.fname,
				lname: req.body.lname
			};
			employee.create(employeeObject, function(err, instance){
				if(err) {
					errorReply("Error creating new employee");
				} else {
					instance.set(employeeObject);
					createVacation(instance.id, req.body.count);
				}
			});
		}

		function createVacation(id, count) {
			var loyalty = Arrow.getModel("vacation");
			var object = {
				"eid": id,
				"count": count
			}
			loyalty.create(object, function(err, instance){
				if(err) {
					errorReply("Error creating new vacation");
				} else {
					instance.set(object);
					successReply(id);
				}
			});
		}

		function errorReply(message) {
			resp.response.status(500);
			resp.send({"success": false,"message":message});
			next(false);
		}

		function successReply(message) {
			resp.response.status(200);
			resp.send({"success": true,"message":message});
			next(false);
		}

	}
});
module.exports = PostBlock;

Then I can modify the employeeAndPoints model to run this block before create (POST) by adding the following property:


"beforeCreate": "createEmployee",

This will cause my block, createEmployee to only run when a create (POST) is called on my composite model.

Curl Command to POST

The curl command to POST an entry in the composite model is shown below:


curl -is -X POST "http://127.0.0.1:8080/api/employeeandvacation" -d '{"fname":"AA","lname":"AA","count":"7"}' -H "Content-Type: application/json"

The curl command to GET a list of employees and their vacations via the composite model is shown below:


curl "http://127.0.0.1:8080/api/employeeandvacation"

with the following response after three POSTs:


{
	"success": true,
	"request-id": "a9c1af65-f258-4099-bed5-4e7b6e75c263",
	"key": "employeeandvacations",
	"employeeandvacations": [
		{
			"id": "57d36a4d1bb9b0091f81f428",
			"fname": "AA",
			"lname": "AA",
			"count": 7
		},
		{
			"id": "57d3697848e64b091d812bfd",
			"fname": "B",
			"lname": "B",
			"count": 15
		},
		{
			"id": "57d3696cb4860e09278345d6",
			"fname": "A",
			"lname": "A",
			"count": 5
		}
	]
}

Summary

While Arrow’s Composite connector enables one to to easily develop complex data aggregation APIs, it does not yet provide a means for inserting any logic in between the back-end data calls. In this blog post we saw how we can create more complex API by inserting transaction logic using javascript code in a block. This provides for more fine-grained control over the API operations.

13 Flares Twitter 0 Facebook 0 Google+ 1 LinkedIn 12 Email -- 13 Flares ×

Sign up for our blog!

Become a mobile leader. Take the first step to scale mobile innovation throughout your enterprise.
Get in touch
computer and tablet showing Appcelerator software
Start free, grow from there.
13 Flares Twitter 0 Facebook 0 Google+ 1 LinkedIn 12 Email -- 13 Flares ×