Skip to content

3. Aprendendo sobre Models

Ingo Guilherme Both Eyng edited this page Jun 8, 2018 · 6 revisions

Caso não tenha visto a segunda parte, peço que dê uma pequena pausa e dê uma olhada nela, já que vamos dar continuidade a partir daquele.

Projeto completo feito nesse tutorial para download.

Models

Neste artigo vamos tratar sobre os models, como vimos anteriormente os controllers é que manipulam os dados, porém eles não devem ser responsáveis por eles, ai que entram os models, vamos então criar um model para os nossos dados das tasks. Cria uma pasta models e dentro dela o arquivo task.js

Windows

mkdir models
cd models
type nul > task.js

Linux

mkdir models
touch models/task.js

Agora que o nosso arquivo model para as tasks está criado, vamos fazer um método para retornar todos os nossos registros. No arquivo models/task.js adicione o seguinte trecho de código:

models/task.js

var tasks = {
	data: [
		{_id: 1, title: 'Limpar a casa', status: 0, created_at: new Date()},
		{_id: 2, title: 'Lavar o carro', status: 0, created_at: new Date()}
	]
};

function all () {
	return tasks;
}

module.exports = {all};

Agora que os dados estão no model da task, precisamos alterar o controller da task, assim ele poderá pegar os dados do model. Também precisamos importar o models, lembra do Consign?? Vamos usá-lo para esta tarefa novamente.

O arquivo bootstrap/app.js ficará assim após adicionar os models no Consign:

bootstrap/app.js

var logger = require('morgan');
var express = require('express');
var consign = require('consign');

var app = express();

app.use(logger('dev'));

consign()
	.include('models') //Adicionamos a pasta "models" ao Consign
	.then('controllers')
	.then('routes')
	.into(app);

module.exports = app;

var port = process.env.PORT || 3000;

app.listen(port, function () {
    console.log('Servidor rodando em http://localhost:%s', port);
});

E o arquivo controllers/task.js vai ter uma alteração, chamando então a função de models/task.js, ficará assim:

controllers/task.js

module.exports = function (app) {
	var Task = app.models.task;

	return {
		index: function (request, response) {
			response.json(Task.all());
		}
	}
}

Note que fizemos algumas alterações, desta maneira o controller é capaz de buscar no model de task a função ´all´.

Criando POST

Agora que já conseguimos listar todas as nossas tarefas, vamos adicionar novas tarefas, para isso vamos criar uma nova rota, um POST. No arquivo routes/index.js adicione o seguinte trecho de código:

app.post('/', app.controllers.task.store);

Ficando assim:

routes/index.js

module.exports = function (app) {
	app.get('/', app.controllers.task.index);
	app.post('/', app.controllers.task.store);
}

Mas ainda não tempos o método store, portanto vamos criá-lo no nosso controller. Ele ficará assim:

controllers/task.js

module.exports = function (app) {
	var Task = app.models.task

	return {
		index: function (request, response) {
			response.json(Task.all());
		},
		store: function (request, response) {
			console.log(request.body);
		}
	}
}

Para fazer o teste deste POST você pode utilizar o Postman já citado no segundo artigo, note que não vamos receber nada no console pois o express não realiza o parse do POST recebido, para isso vamos utilizar outro módulo o Body Parser.

:octocat: GitHub Link

O Body Parser é um middleware para NodeJS. Ele faz a analise (parse) do body das requisições recebidas antes dos manipuladores.

Após essa breve explicação sobre o Body Parser, vamos instalá-lo.

NodeJS

npm i body-parser --save 

Depois de instalar, vamos configurá-lo no nosso arquivo bootstrap/app.js. O arquivo fica assim:

bootstrap/app.js

var logger = require('morgan');
var express = require('express');
var consign = require('consign');
var bodyParser = require('body-parser');

var app = express();

app.use(logger('dev'));

app.use(bodyParser.urlencoded({
  extended: true
}));

consign()
	.include('models')
	.then('controllers')
	.then('routes')
	.into(app);

module.exports = app;

var port = process.env.PORT || 3000;

app.listen(port, function () {
    console.log('Servidor rodando em http://localhost:%s', port);
});

Agora que já temos o Body Parser configurado, se fizermos um POST novamente (lembrando de enviar como urlencoded), vamos ter os dados enviados no post no request.body;

Salvando novas tarefas

Tendo a aplicação configurada e pronta para receber POSTS, vamos adicionar a nova tarefa a nossa lista de tarefas. Em nosso controllers/task.js vamos alterar o método store. O arquivo vai ficar assim:

controllers/task.js

module.exports = function (app) {
	var Task = app.models.task

	return {
		index: function (request, response) {
			response.json(Task.all());
		},
		store: function (request, response) {
			Task.save({
				title: request.body.title, //Título da tarefa passado no POST
				status: 0, 
				created_at: new Date() //Data do momento em que o store foi chamado
			});

			response.redirect('/'); //Redireciona para a página principal
		}
	}

}

Com nosso controller pronto, estamos chamando a função save de task e logo após realizando o redirect para nossa raiz, assim logo após o salvar a nova tarefa, retornamos a página inicial.

Mas como não temos a função save ainda, vamos então criar o método em nosso model. No arquivo models/task.js vamos inserir o método save, ficando assim:

controllers/task.js

var tasks = {
	data: [
		{_id: 1, title: 'Limpar a casa', status: 0, created_at: new Date()},
		{_id: 2, title: 'Lavar o carro', status: 0, created_at: new Date()}
	]
};

function all () {
	return tasks;
}

function save(task) {
	//Pegamos o índice da última tarefa somado com um, para criar o índice da nova tarefa.
	task._id = tasks.data[tasks.data.length - 1]._id + 1;

	//Adicionamos a nova task a nossa lista de tasks
	tasks.data.push(task);
}

module.exports = {all, save}; //Adicionar função save ao vetor do exports

Agora é só realizar o POST (urlencoded) para localhost:3000 enviando title como key e o nome da tarefa como value para inserir uma nova tarefa na lista.

Lembrando que como não fazemos persistência de dados em nenhum banco de dados, por hora, ele salva essa lista somente em tempo de execução do servidor.

Você pode notar pelo Postman que a nova tarefa foi adicionada após o POST pois ele faz o redirecionamento para a página inicial, a qual é um GET da lista de tarefas e retorna como response do POST (´response.redirect('/');´).

Editando tarefas (Revisar a partir daqui)

Editar não é uma tarefa tão simples como cadastrar uma tarefa, nós precisaremos buscar a tarefa para então editá-la. Mas vamos começar criando uma nova rota para realizar a atualização desta tarefa. No arquivo routes/index.js adicione a nova rota app.post('/task/:id', app.controllers.task.update);.

routes/index.js

module.exports = function (app) {
	app.get('/', app.controllers.task.index);
	app.post('/', app.controllers.task.store);
	app.post('/task/:id', app.controllers.task.update);
}

Assim é possível realizar um POST na rota localhost:3000/task/1 por exemplo, onde :id (1) é o parâmetro que recebemos através da rota.

Feito isso vamos criar a função de update em nosso controllers/task.js, ficando assim:

controllers/task.js

module.exports = function (app) {
	var Task = app.models.task

	return {
		index: function (request, response) {
			response.json(Task.all());
		},
		store: function (request, response) {
			Task.save({
				title: request.body.title, //Título da tarefa passado no POST
				status: 0, 
				created_at: new Date() //Data do momento em que o store foi chamado
			});

			response.redirect('/');
		},
		update: function (request, response) {
			//Recupera o id como parametro do link da task que deseja alterar
			var id = request.params.id; 

			//Recupera os novos valores da task enviados no body
			var task = request.body; 

			//Chama a função update no model de task
			Task.update(id, task);

			response.redirect('/');
		}
	}

}

Agora que temos nossa rota e nosso controller prontos, vamos criar a função de update no model da task. O arquivo models/task.js com a função update ficaria:

models/task.js

var tasks = {
	data: [
		{_id: 1, title: 'Limpar a casa', status: 0, created_at: new Date()},
		{_id: 2, title: 'Lavar o carro', status: 0, created_at: new Date()}
	]
};

function all() {
	return tasks;
}

function save(task) {
	task._id = tasks.data[tasks.data.length - 1]._id + 1;
	tasks.data.push(task);
}

//Função update
function update (id, task) {
	//Recuperamos o index da tarefa na nossa lista
	var index = tasks.data.findIndex(function (task) {
		return task._id == id
	});

	//Alteramos o valor da tarefa correspondente 
	tasks.data[index].title = task.title;
	tasks.data[index].status = task.status;

	return
}

//Adicionamos a função update ao vetor
module.exports = {all, save, update};

Agora é só realizar o POST para localhost:3000/task/:id enviando title como key e o nome da tarefa como value para editar uma tarefa na lista.

Lembrando que como não fazemos persistência de dados em nenhum banco de dados, por hora, ele salva essa lista somente em tempo de execução do servidor.

Você pode notar pelo Postman que a nova tarefa foi alterada após o POST pois ele faz o redirecionamento para a página inicial, a qual é um GET da lista de tarefas e retorna como response do POST (´response.redirect('/');´), Então pode-se ver que a tarefa cujo id nos passamos foi alterada.

Deletando tarefas

Deletar uma tarefa, é bem parecido com alterar uma, primeiro vamos adicionar uma nova rota. No arquivo routes/index.js adicione a nova rota app.get('/task/:id', app.controllers.task.destroy);.

routes/index.js

module.exports = function (app) {
	app.get('/', app.controllers.task.index);
	app.post('/', app.controllers.task.store);
	app.post('/task/:id', app.controllers.task.update);
	app.get('/task/:id', app.controllers.task.destroy);
}

Assim é possível realizar um GET na rota localhost:3000/task/1 por exemplo, onde :id (1) é o parâmetro que recebemos através da rota e será usado para deletar a rota com o mesmo id.

Feito isso vamos criar a função de destroy em nosso controllers/task.js, ficando assim:

controllers/task.js

module.exports = function (app) {
	var Task = app.models.task

	return {
		index: function (request, response) {
			response.json(Task.all());
		},
		store: function (request, response) {
			Task.save({
				title: request.body.title, //Título da tarefa passado no POST
				status: 0, 
				created_at: new Date() //Data do momento em que o store foi chamado
			});

			response.redirect('/');
		},
		update: function (request, response) {
			var id = request.params.id; 
			var task = request.body; 
			Task.update(id, task);

			response.redirect('/');
		},
		destroy: function (request, response) {
			//Chama a função remove no model de task passando id como parâmetro
			Task.remove(request.params.id);
			response.redirect('/');
		}
	}

}

Agora que temos nossa rota e nosso controller prontos, vamos criar a função de remove no model da task. O arquivo models/task.js com a função remove ficaria:

models/task.js

var tasks = {
	data: [
		{_id: 1, title: 'Limpar a casa', status: 0, created_at: new Date()},
		{_id: 2, title: 'Lavar o carro', status: 0, created_at: new Date()}
	]
};

function all() {
	return tasks;
}

function save(task) {
	task._id = tasks.data[tasks.data.length - 1]._id + 1;
	tasks.data.push(task);
}

function update (id, task) {
	//Recuperamos o index da tarefa na nossa lista
	var index = tasks.data.findIndex(function (task) {
		return task._id == id
	});

	//Alteramos o valor da tarefa correspondente 
	tasks.data[index].title = task.title;
	tasks.data[index].status = task.status;

	return
}

//Função remove
function remove(id) {
	//Criado nova lista de tarefas, excluindo a que possui id igual ao enviado por parâmetro
	tasks.data = tasks.data.filter(function (task) {
		return task._id != id;
	})

	return
}

//Adicionamos a função remove ao vetor
module.exports = {all, save, update, remove};

Agora é só realizar o GET para localhost:3000/task/:id, onde o id enviado como parâmetro será usado para remover o tarefa da correspondente da lista.

Lembrando que como não fazemos persistência de dados em nenhum banco de dados, por hora, ele salva essa lista somente em tempo de execução do servidor.

Você pode notar pelo Postman que a nova tarefa foi removida após o POST pois ele faz o redirecionamento para a página inicial, a qual é um GET da lista de tarefas e retorna como response do POST (´response.redirect('/');´), Então pode-se ver que a tarefa cujo id nos passamos não está mais presente.

Projeto completo feito nesse tutorial para download.