- Create a full CRUD hobbies app with views in Express, and Node- using dummy seed data.
- Add a postgres database and the sequelize CLI.
- Update routes to accomodate this.
hobbies
- name (string/varchar(255))
- description (string/varchar(255))
- difficulty (float/integer)
- levelOfProfficiency (float/integer)
- hoursPracticed (float/integer)
express --view=ejs --git myApp
cd myApp
npm install
atom .
npm install express-ejs-layouts --save
npm install method-override --save
npm install body-parser --save
var ejsLayouts = require('express-ejs-layouts');
var methodOverride = require('method-override');
var bodyParser = require('body-parser');
app.use(ejsLayouts);
app.use(methodOverride('_method'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
- add
views/layout.ejs
, and DRY up the views/index.ejs
<!DOCTYPE html>
<html>
<head>
<title>My Hobbies App</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<div class="container">
<%- body %>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
- add
"start:dev": "nodemon ./bin/www"
- start the server- npm run start:dev
- go to localhost:3000 to make sure that you didn't break anything
- git init...
- git commit
touch routes/hobbies_controller.js
const express = require('express');
const router = express.Router();
module.exports = router;
var hobbiesController = require('./routes/hobbies_controller');
app.use('/hobbies', hobbiesController);
mkdir db
touch db/hobbies_data.js
module.exports = {
seededHobbies: [
{
name: "playing guitar",
description: "6 stringed instrument- nylon vs steel strings, classical vs flamenco, acoustic vs electric",
difficulty: 3,
levelOfProfficiency: 3,
hoursPracticed: 5
},
{
name: "drawing",
description: "pencil to paper",
difficulty: 2,
levelOfProfficiency: 2,
hoursPracticed: 1
}
]
};
var data = require('../db/hobbies_data').seededHobbies;
- git commit...
// index route
router.get('/', (req, res) => {
res.send('we did it');
});
- chcek in postman/browser
- git commit...
mkdir views/hobbies
touch views/hobbies/index.ejs
- add a dummy h1-
<h1>My Hobbies</h1>
// index route
router.get('/', (req, res) => {
// res.send('we did it');
res.render('hobbies/index');
});
- chcek in postman/browser
- git commit...
<h1>My Hobbies</h1>
<% if (hobbies && hobbies.length) { %>
<ul>
<% hobbies.forEach((hobby) => { %>
<li class="margin-bottom">
<h2><a href="/hobbies/<%= id %>"><%= hobby.name %></a></h2>
</li>
<% }); %>
<a class="btn btn-outline-info margin-top" href="/hobbies/new">Add a New Hobby</a>
</ul>
<% } else { %>
<h3>You don't have any hobbies!</h3>
<a class="btn btn-outline-info margin-top" href="/hobbies/new">Add a New Hobby</a>
<% } %>
body {
margin: 10vh 0px;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
font-size: 1em;
text-align: center;
}
h1, .margin-bottom {
margin-bottom: 50px;
}
.margin-top {
margin-top: 50px;
}
.sm-margin-top {
margin-top: 25px;
}
ul {
list-style-type: none;
padding-left: 0px;
}
a {
color: #68b3c2;
}
- check in postman/browser
- git commit...
// show route
router.get('/:id', (req, res) => {
res.send('we showed it');
});
- check in postman/browser
- git commit...
touch views/hobbies/show.ejs
// show route
router.get('/:id', (req, res) => {
// res.send('we showed it');
var hobby = data[req.params.id];
res.render('hobbies/show', {
id: req.params.id,
hobby: hobby
});
});
<h1><%= hobby.name %></h1>
<h3>description: <%= hobby.description %></h3>
<br />
<p>
<strong>difficulty:</strong> <%= hobby.difficulty %>,
<strong>level of profficiency:</strong> <%= hobby.levelOfProfficiency %>
</p>
<p>
<strong>hours practiced:</strong> <%= hobby.hoursPracticed %>
</p>
<a class="btn btn-outline-info margin-top" href="/hobbies/<%= id %>/edit">edit hobby</a>
- check in postman/browser
- git commit...
router.get('/new', (req, res) => {
res.send('we knew it');
});
- check in postman/browser
- git commit...
touch views/hobbies/new.ejs
<h1>Add a New Hobby!</h1>
<form>
<div class="form-group">
<label for="name">Hobby Name <span class="red">(required)</span></label>
<input class="form-control" type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="description">Description</label>
<input class="form-control" type="text" id="description" name="description">
</div>
<div class="form-group">
<label for="difficulty">Difficulty</label>
<input class="form-control" type="number" id="difficulty" min="0" max="5" step="0.05" name="difficulty">
</div>
<div class="form-group">
<label for="levelOfProfficiency">Level of Profficiency</label>
<input class="form-control" type="number" id="levelOfProfficiency" min="0" max="5" step="0.05" name="levelOfProfficiency">
</div>
<div class="form-group">
<label for="hoursPracticed">Hours Practiced</label>
<input class="form-control" type="number" id="hoursPracticed" step="0.05" name="hoursPracticed">
</div>
<div class="form-group">
<input class="btn btn-outline-info"" type="submit" value="Submit">
</div>
</form>
<a class="btn btn-outline-info margin-top" href="/hobbies">back</a>
- check in postman/browser
- git commit...
// create route
router.post('/', (req, res) => {
var newHobby = req.body;
data.seededHobbies.push(newHobby);
res.redirect('/hobbies');
});
<form action="/hobbies" method="POST">
- check in postman/browser
- git commit...
// edit route
router.get('/:id/edit', (req, res) => {
res.send('we do it');
});
- check in postman/browser
- git commit...
touch views/hobbies/edit.ejs
// edit route
router.get('/:id/edit', (req, res) => {
// res.send('we do it');
var hobbyToEdit = data[req.params.id];
res.render('hobbies/edit', {
id: req.params.id,
hobby: hobbyToEdit
});
});
<h1>Edit your '<%= hobby.name %>' Hobby!</h1>
<form action="/hobbies/<%= id %>?_method=PUT" method="POST">
<div class="form-group">
<label for="name">Hobby Name <span class="red">(required)</span></label>
<input class="form-control" type="text" name="name" value="<%= hobby.name %>">
</div>
<div class="form-group">
<label for="description">Description</label>
<input class="form-control" type="text" name="description" value="<%= hobby.description %>">
</div>
<div class="form-group">
<label for="difficulty">Difficulty</label>
<input class="form-control" type="number" name="difficulty" value="<%= hobby.difficulty %>" min="0" max="5" step="0.05">
</div>
<div class="form-group">
<label for="levelOfProfficiency">Level of Profficiency</label>
<input class="form-control" type="number" name="levelOfProfficiency" value="<%= hobby.levelOfProfficiency %>" min="0" max="5" step="0.05">
</div>
<div class="form-group">
<label for="hoursPracticed">Hours Practices</label>
<input class="form-control" type="number" name="hoursPracticed" value="<%= hobby.hoursPracticed %> step="0.05">
</div>
<div class="form-group">
<input class="btn btn-outline-info margin-top" type="submit" value="Submit">
</div>
</form>
<a class="btn btn-outline-info margin-top" href="/hobbies/<%= id %>">back</a>
- check in postman/browser
- git commit...
// update route
router.put('/:id', (req, res) => {
var editedHobby = req.body;
data[req.params.id] = editedHobby;
res.render('hobbies/show', {
id: req.params.id,
hobby: editedHobby
});
});
- check in postman/browser
- git commit...
// delete route
router.delete('/:id', (req, res) => {
// remove the item from the array
data.splice(req.params.id, 1);
// redirect back to index route
res.redirect('/hobbies');
});
<form action="/hobbies/<%= id %>?_method=DELETE" method="POST">
<input class="btn btn-outline-danger sm-margin-top" type="submit" value="Delete Hobby" />
</form>
- check in postman/browser
- git commit...
npm install --save sequelize
npm install --save pg pg-hstore
npm install --save sequelize-cli
sequelize init
- config
- config.json
- models
- index.js
- seeders
- migrations
{
"development": {
"database": "hobbies",
"host": "127.0.0.1",
"dialect": "postgres"
},
"test": {
"database": "hobbies_test",
"host": "127.0.0.1",
"dialect": "postgres"
},
"production": {
"database": "hobbies_production",
"host": "127.0.0.1",
"dialect": "postgres"
}
}
createdb hobbies
psql
\l
\c hobbies
\d
\q
- git commit...
touch routes/hobbies_controller_sequelize.js
// var hobbiesController = require('./routes/hobbies_controller');
var hobbiesController = require('./routes/hobbies_controller_sequelize');
- git commit...
sequelize model:create --name hobby -- attributes name:string,description:string,difficulty:float,levelOfProfficiency:float,hoursPracticed:float
sequelize db:migrate
- git commit...
const Hobby = require('../models').hobby;
- git commit...
// index route
router.get('/', (req, res) => {
// res.send('we did it');
Hobby.findAll()
.then((hobbies) => {
res.render('hobbies/index', {
hobbies: hobbies
});
})
.catch((err) => {
res.status(400).render('error');
});
});
...
<h2><a href="/hobbies/<%= hobby.id %>"><%= hobby.name %></a></h2>
...
- check in postman/browser
- git commit...
// show route
router.get('/:id', (req, res) => {
// res.send('we showed it');
Hobby.findById(req.params.id)
.then((hobby) => {
res.render('hobbies/show', {
hobby: hobby
});
})
.catch((err) => {
res.status(400).render('error');
});
});
- check in postman/browser
- git commit...
...
<a class="btn btn-outline-info margin-top" href="/hobbies/<%= hobby.id %>/edit">edit hobby</a>
<form action="/hobbies/<%= hobby.id %>?_method=DELETE" method="POST">
<input class="btn btn-outline-danger sm-margin-top" type="submit" value="delete hobby" />
</form>
- check in postman/browser
- git commit...
// new route
router.get('/new', (req, res) => {
// res.send('we knew it');
res.render('hobbies/new', {
// building an instance of hobby
hobby: Hobby.build()
})
.catch((err) => {
res.status(400).render('error');
});
});
- check in postman/browser
- git commit...
// create route
router.post('/', (req, res) => {
// requires an object with properties that map to the properties of the object
Hobby.create(req.body)
.then((hobby) => {
res.redirect('/hobbies');
})
.catch((err) => {
res.status(400).render('error');
});
});
- check in postman/browser
- git commit...
// edit route
router.get('/:id/edit', (req, res) => {
// res.send('we do it');
Hobby.findById(req.params.id)
.then((hobby) => {
res.render('hobbies/edit', {
hobby: hobby
});
})
.catch((err) => {
res.status(400).render('error');
});
});
<form method="POST" action="/hobbies/<%= hobby.id %>?_method=PUT">
...
<a class="btn btn-outline-info margin-top" href="/hobbies/<%= hobby.id %>">back</a>
- check in postman/browser
- git commit...
// update route
router.put('/:id', (req, res) => {
Hobby.findById(req.params.id)
.then((hobby) => {
return hobby.update(req.body); // update method returns a promise
})
.then((updatedHobby) => { // the hobby parameter is the updated hobby
res.render('hobbies/show', {
hobby: updatedHobby
});
})
.catch((err) => {
res.status(400).render('error');
});
});
- check in postman/browser
- git commit...
// delete route
router.delete('/:id', (req, res) => {
Hobby.findById(req.params.id)
.then((hobby) => {
return hobby.destroy(); // destroy method is an asynchronous call that returns a promise
})
.then(() => {
// redirect back to index route
res.redirect('/hobbies');
})
.catch((err) => {
res.status(400).render('error');
});
});
- check in postman/browser
- git commit...
sequelize seed:create --name my-seed-file
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
/*
Add altering commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.bulkInsert('Person', [{
name: 'John Doe',
isBetaMember: false
}], {});
*/
return queryInterface.bulkInsert('hobbies', [{
name: 'playing guitar',
description: "6 stringed instrument- nylon vs steel strings, classical vs flamenco, acoustic vs electric",
difficulty: 3,
levelOfProfficiency: 3,
hoursPracticed: 5
},
{
name: "drawing",
description: "pencil to paper",
difficulty: 2,
levelOfProfficiency: 2,
hoursPracticed: 1
}
], {});
},
down: (queryInterface, Sequelize) => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.bulkDelete('Person', null, {});
*/
return queryInterface.bulkDelete('hobbies', null, {});
}
};
sequelize db:seed:all
sequelize db:migrate
- check in postman/browser