Sequelize e Express no Node.js
Vamos criar uma aplicação web simples utilizando Express, que interage com o banco de dados SQLite através do Sequelize. Primeiro, definimos um novo projeto e adicionamos os pacotes necessários:
npm install --save hbs express sqlite3 sequelize
Para a parte visual, utilizaremos os templates do Handlebars. Para isso, criamos a pasta views
no projeto. Dentro dela, adicionamos um novo arquivo chamado index.hbs
:
<!DOCTYPE html>
<html>
<head>
<title>Lista de Usuários</title>
<meta charset="utf-8" />
</head>
<body>
<h1>Lista de Usuários</h1>
<p><a href="/create">Adicionar Usuário</a></p>
<table>
<tr>
<th>Nome</th>
<th>Idade</th>
<th></th>
</tr>
{{#each users}}
<tr>
<td>{{this.name}}</td>
<td>{{this.age}}</td>
<td>
<a href="/edit/{{this.id}}">Editar</a>|
<form action="delete/{{this.id}}" method="POST" style="display:inline;">
<input type="submit" value="Deletar" />
</form>
</td>
</tr>
{{/each}}
</table>
</body>
</html>
Essa view exibe uma lista de objetos em forma de tabela, permitindo sua edição e exclusão. Acima da tabela, há um link para adicionar novos objetos.
Em seguida, adicionamos um novo arquivo create.hbs
na pasta views
, que contém um formulário para criar um novo objeto:
<!DOCTYPE html>
<html>
<head>
<title>Adicionar Usuário</title>
<meta charset="utf-8" />
<style>
.field {
width: 180px;
}
</style>
</head>
<body>
<h1>Adicionar Usuário</h1>
<form method="POST">
<label>Nome</label><br />
<input name="name" class="field" /><br /><br />
<label>Idade</label><br />
<input name="age" type="number" class="field" min="1" max="110" /><br /><br />
<input type="submit" value="Enviar" />
</form>
<a href="/">Voltar à lista de usuários</a>
</body>
</html>
Na pasta views
, também adicionamos um novo arquivo edit.hbs
, que contém um formulário para editar um objeto existente:
<!DOCTYPE html>
<html>
<head>
<title>Editar Usuário</title>
<meta charset="utf-8" />
<style>
.field {
width: 180px;
}
</style>
</head>
<body>
<h1>Editar Usuário</h1>
<form action="/edit" method="POST">
<input type="hidden" name="id" value="{{user.id}}" />
<label>Nome</label><br />
<input name="name" value="{{user.name}}" class="field" /><br /><br />
<label>Idade</label><br />
<input name="age" type="number" min="1" max="110" value="{{user.age}}" class="field" /><br /><br />
<input type="submit" value="Enviar" />
</form>
<a href="/">Voltar à lista de usuários</a>
</body>
</html>
Por fim, definimos o arquivo principal da aplicação,app.js
, na pasta raiz do projeto:
const Sequelize = require("sequelize");
const express = require("express");
const app = express();
const urlencodedParser = express.urlencoded({ extended: false });
// Definimos o objeto Sequelize
const sequelize = new Sequelize({
dialect: "sqlite",
storage: "programicio.db",
define: {
timestamps: false,
},
});
// Definimos o modelo User
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
age: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
app.set("view engine", "hbs");
// Sincronizamos com o banco de dados; após sincronização bem-sucedida, iniciamos o servidor
sequelize
.sync()
.then(() => {
app.listen(3000, function () {
console.log("Servidor aguardando conexões...");
});
})
.catch((err) => console.log(err));
// Rota para obter dados
app.get("/", function (req, res) {
User.findAll({ raw: true })
.then((data) => {
res.render("index.hbs", {
users: data,
});
})
.catch((err) => console.log(err));
});
app.get("/create", function (req, res) {
res.render("create.hbs");
});
// Rota para adicionar dados
app.post("/create", urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
const username = req.body.name;
const userage = req.body.age;
User.create({ name: username, age: userage })
.then(() => {
res.redirect("/");
})
.catch((err) => console.log(err));
});
// Rota para obter objeto por id para edição
app.get("/edit/:id", function (req, res) {
const userid = req.params.id;
User.findAll({ where: { id: userid }, raw: true })
.then((data) => {
res.render("edit.hbs", {
user: data[0],
});
})
.catch((err) => console.log(err));
});
// Rota para atualizar dados no banco de dados
app.post("/edit", urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
const username = req.body.name;
const userage = req.body.age;
const userid = req.body.id;
User.update({ name: username, age: userage }, { where: { id: userid } })
.then(() => {
res.redirect("/");
})
.catch((err) => console.log(err));
});
// Rota para deletar dados
app.post("/delete/:id", function (req, res) {
const userid = req.params.id;
User.destroy({ where: { id: userid } })
.then(() => {
res.redirect("/");
})
.catch((err) => console.log(err));
});
A estrutura do projeto:
MYSQLAPP ├── node_modules ├── views │ ├── create.hbs │ ├── edit.hbs │ └── index.hbs ├── app.js └── package.json
Ao acessar a raiz da aplicação, é executado o método abaixo:
app.get("/", function (req, res) {
User.findAll({ raw: true })
.then((data) => {
res.render("index.hbs", {
users: data,
});
})
.catch((err) => console.log(err));
});
Esse método obtém os dados do banco de dados e os envia para a view index.hbs
. Se o banco de dados já contiver algum dado, ao iniciar a aplicação, esses dados serão exibidos na página.
Ao clicar no link de adição de um novo usuário, o servidor recebe uma requisição GET, que será processada pelo seguinte método:
app.get("/create", function (req, res) {
res.render("create.hbs");
});
Este método retorna ao cliente o formulário para adição de novos usuários:
Após o envio do formulário, os dados são enviados em uma requisição POST ao método abaixo:
app.post("/create", urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
const username = req.body.name;
const userage = req.body.age;
User.create({ name: username, age: userage })
.then(() => {
res.redirect("/");
})
.catch((err) => console.log(err));
});
Esse método recebe os dados do formulário e os envia ao banco de dados.
Ao clicar no link de edição de um usuário na lista de objetos, o id
do objeto é passado para o próximo método em uma requisição GET:
app.get("/edit/:id", function (req, res) {
const userid = req.params.id;
User.findAll({ where: { id: userid }, raw: true })
.then((data) => {
res.render("edit.hbs", {
user: data[0],
});
})
.catch((err) => console.log(err));
});
Esse método recebe o id
, extrai o objeto correspondente do banco de dados e o envia ao formulário no template edit.hbs
:
Após a edição e o envio do formulário, os dados são enviados em uma requisição POST para o método a seguir:
app.post("/edit", urlencodedParser, function (req, res) {
if (!req.body) return res.sendStatus(400);
const username = req.body.name;
const userage = req.body.age;
const userid = req.body.id;
User.update({ name: username, age: userage }, { where: { id: userid } })
.then(() => {
res.redirect("/");
})
.catch((err) => console.log(err));
});
Esse método recebe os dados atualizados e os envia ao banco de dados.
Ao clicar no botão de exclusão de um usuário na lista de objetos, o método abaixo é executado:
app.post("/delete/:id", function(req, res) {
const userid = req.params.id;
User.destroy({where: {id: userid} }).then(() => {
res.redirect("/");
}).catch(err => console.log(err));
Esse método recebe o id
do objeto a ser excluído e o remove do banco de dados.