Services

Last updated 6 months ago

A service in Blueprint is a software component that operate in the background of the application, and outside of the controllers, routers, and listeners. Services can also be references by other software components, including services themselves. For example, you could recreate a service that performs periodic background tasks, or a service that manages connections to a database.

In our example, we want to migrate the data stored in the rental controller to a service. This will allow different software entities in the Blueprint application, such as another controller, to reference the same data as the rental controller.

Defining the Service

First, lets generate the service using the Blueprint cli.

blueprint generate service rentals

This command will generate an empty service.

app/services/rentals.js
const { Service, computed } = require ('@onehilltech/blueprint');
/**
* @class rentals
*/
module.exports = Service.extend ({
});

The service is automatically loaded by the Blueprint application when started.

Implementing the Service

For the service, we need a method for adding rentals, deleting rentals, getting all the rentals, and getting a single rental. We are also going to initialize the service with the original data.

app/services/rentals.js
const { Service, computed } = require ('@onehilltech/blueprint');
/**
* @class rentals
*/
module.exports = Service.extend ({
_rentals: null,
rentals: computed ({
get () { return this._rentals; }
}),
init () {
this._super.call (this, ...arguments);
this._rentals = [
{
type: 'rentals',
id: 'grand-old-mansion',
attributes: {
title: 'Grand Old Mansion',
owner: 'Veruca Salt',
city: 'San Francisco',
category: 'Estate',
bedrooms: 15,
image: 'https://upload.wikimedia.org/wikipedia/commons/c/cb/Crane_estate_(5).jpg'
}
},
{
type: 'rentals',
id: 'urban-living',
attributes: {
title: 'Urban Living',
owner: 'Mike Teavee',
city: 'Seattle',
category: 'Condo',
bedrooms: 1,
image: 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Alfonso_13_Highrise_Tegucigalpa.jpg'
}
},
{
type: 'rentals',
id: 'downtown-charm',
attributes: {
title: 'Downtown Charm',
owner: 'Violet Beauregarde',
city: 'Portland',
category: 'Apartment',
bedrooms: 3,
image: 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Wheeldon_Apartment_Building_-_Portland_Oregon.jpg'
}
}];
},
// get a single rental
get (id) {
return this._rentals.find (rental => rental.id === id);
},
// add a rental to the list.
add (rental) {
return this._rentals.push (rental);
},
// remove the rental from the list.
remove (id) {
let index = this._rentals.findIndex (rental => rental.id === id);
if (index === -1)
return false;
this._rentals.splice (index, 1);
return true;
}
});

Using the Service

Let's go back to our rental controller and re-implement the rental.get using the rentals service from above. To load a service into the rental controller, just use the service computed property.

app/controllers/rental.js
const {
Controller,
Action,
service // computed property for loading a service
} = require ('@onehilltech/blueprint');
/**
* @class rental
*/
module.exports = Controller.extend ({
// load the rentals service, name parameter is not needed
rentals: service (),
get () {
return Action.extend ({
execute (req, res) {
// get the data from the rentals service
const data = this.controller.rentals.rentals;
res.status (200).json ({data});
}
})
}
});

Let's break down the example above since we have made some changes to the original controller code. First, we load the service into the controller using the service() computed property function, which is available via the rentals property on the controller. Next, we updated the get() action implementation to retrieve the rental data from the service.

All actions can access to the parent controller using thethis.controller property.

Now, when you restart the application and open the browser to http://localhost:5000/api/rentals, you will get the same response as before. The only difference this time is the data is pulled from the rentals service, and not from local data in the controller.