mkdir express-movies
cd express-movies
express -e
npm install
npm install --save method-override
npm install --save mongoose
bower install bootstrap
# copy static client-side assets to public folder
cp bower_components/bootstrap/dist/css/bootstrap.min.css public/stylesheets/
cp bower_components/bootstrap/dist/js/bootstrap.min.js public/javascripts/
cp bower_components/jquery/dist/jquery.min.js public/javascripts/
Edit package.json
and replace node
with nodemon
npm start
git init
touch .gitignore
echo bower_components >> .gitignore
echo node_modules >> .gitignore
git add -A
git commit -m "Project setup completed."
Add the following to the file views/index.ejs
:
<!-- add this link to the head section -->
<link rel='stylesheet' href='/stylesheets/bootstrap.min.css' />
.
.
.
<!-- add these scripts just after the body section -->
<script type="text/javascript" src="/javascripts/jquery.min.js" defer></script>
<script type="text/javascript" src="/javascripts/bootstrap.min.js" defer></script>
Edit app.js
and add the following code:
var mongoose = require('mongoose');
var methodOverride = require('method-override');
.
.
.
// Put these lines just after creating the `app`:
// Connect to database
mongoose.connect('mongodb://localhost/express-movies');
.
.
.
// Put this line just above your routes
app.use(methodOverride('_method'));
npm start
Load / Refresh the browser tab and look for any console errors (check in browser and in Terminal)
git add -A
git commit -m "Added bootrap and jQuery links. Configured Mongoose and method-override."
Add a Bootstrap NavBar:
8a. Create the partial files:
mkdir views/partials
touch views/partials/head.ejs
touch views/partials/header.ejs
touch views/partials/footer.ejs
8b. Set the contents of views/partials/head.ejs
to the following:
<title>Express Movies</title>
<link rel='stylesheet' href='/stylesheets/bootstrap.min.css' />
<link rel='stylesheet' href='/stylesheets/style.css' />
8c. Set the contents of views/partials/header.ejs
to the following:
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">
<span class="glyphicon glyphicon glyphicon-tree-deciduous"></span>Express Movies
</a>
</div>
<ul class="nav navbar-nav navbar-left">
<li><a href="/">Home</a></li>
<li><a href="/movies">Movies</a></li>
</ul>
</div>
</nav>
8d. Set the contents of views/partials/footer.ejs
to the following:
<p class="text-center text-muted">© Copyright 2016 ATLANTA WDI</p>
8e. Set the contents of views/index.ejs
with the following:
<!doctype html>
<html lang="en">
<head>
<% include partials/head %>
</head>
<body class="container-fluid">
<header>
<% include partials/header %>
</header>
<main>
<div class="jumbotron">
<h1>Welcome to Express Movies</h1>
</main>
<footer>
<% include partials/footer %>
</footer>
</body>
<script type="text/javascript" src="/javascripts/jquery.min.js" defer></script>
<script type="text/javascript" src="/javascripts/bootstrap.min.js" defer></script>
</html>
8f. Copy the Fonts
We are getting some 404s on our Bootstrap fonts so let's copy these files into the appropriate folder under public
:
mkdir public/fonts
cp bower_components/bootstrap/dist/fonts/* public/fonts
9a. Create a movies router file:
touch routes/movies.js
Put the following code inside routes/movies.js
:
var express = require('express');
var router = express.Router();
function makeError(res, message, status) {
res.statusCode = status;
var error = new Error(message);
error.status = status;
return error;
}
let movies = [
{
title: 'Star Wars',
genre: 'Science Fiction',
year: 1977
},
{
title: 'Groundhog Day',
genre: 'Comedy',
year: 1993
}
];
// INDEX
router.get('/', function(req, res, next) {
res.render('movies/index', { movies: movies });
});
module.exports = router;
9b. Create the view for the Movies Index Route:
mkdir views/movies
touch views/movies/index.ejs
Add the following code to views/movies/index.ejs
:
<!DOCTYPE html>
<html lang="en">
<head>
<% include ../partials/head %>
</head>
<body class="container-fluid">
<header>
<% include ../partials/header %>
</header>
<main>
<div>
<h3>Movies:</h3>
<% movies.forEach(function(movie) { %>
<dl class="dl-horizontal">
<dt>Title</dt><dd><%= movie.title %></dd>
<dt>Genre</dt><dd><%= movie.genre %></dd>
<dt>Year</dt><dd><%= movie.year %></dd>
</dl>
<% }) %>
</div>
</main>
<footer>
<% include ../partials/footer %>
</footer>
</body>
</html>
9c. Add movies router to app.js
:
var moviesRouter = require('./routes/movies');
.
.
.
app.use('/movies', moviesRouter);
mkdir models
touch models/movie.js
Add the following code to models/movie.js
:
var mongoose = require('mongoose');
var MovieSchema = new mongoose.Schema({
title: { type: String, required: true },
genre: { type: String, required: true },
year: Number
},
{ timestamps: true } // createdAt, updatedAt
);
module.exports = mongoose.model('Movie', MovieSchema);
Create the seeds file:
touch seeds.js
var mongoose = require('mongoose');
var Movie = require('./models/movie');
mongoose.connect('mongodb://localhost/express-movies');
// our script will not exit until we have disconnected from the db.
function quit() {
mongoose.disconnect();
console.log('\nQuitting!');
}
// a simple error handler
function handleError(err) {
console.log('ERROR:', err);
quit();
return err;
}
console.log('removing old movies...');
Movie.remove({})
.then(function() {
console.log('old movies removed');
console.log('creating some new movies...');
var starWars = new Movie({ title: 'Star Wars', genre: 'Science Fiction', year: 1977 });
var groundhogDay = new Movie({ title: 'Groundhog Day', genre: 'Comedy', year: 1993 });
var terminator = new Movie({ title: 'Terminator', genre: 'Science Fiction', year: 1986 });
return Movie.create([starWars, groundhogDay, terminator]);
})
.then(function(savedMovies) {
console.log('Just saved', savedMovies.length, 'movies.');
return Movie.find({});
})
.then(function(allMovies) {
console.log('Printing all movies:');
allMovies.forEach(function(movie) {
console.log(movie);
});
quit();
});
Make the following changes to routes/movies.js
:
var Movie = require('../models/movie');
.
.
.
// INDEX
router.get('/', function(req, res, next) {
Movie.find({})
.then(function(movies) {
res.render('movies/index', { movies: movies });
});
});
12a. Create an Heroku Account
12b. Install the Heroku Toolbelt onto your computer:
12c. Configure this project for Heroku Deployment
heroku create
git remote -v # Displays the newly creates Git remotes for Heroku
12d. Deploy project by Git pushing to Heroku
git push heroku master
# After that completes run:
heroku ps
# To investigate errors run:
heroku logs
12e. Add MongoLab to Project
heroku addons:create mongolab:sandbox
The above command will automatically set a heroku environment variable. To see the value, just run:
heroku config
Edit app.js
and seeds.js
and replace the existing DB connection code with the following:
// Connect to database
if (process.env.MONGODB_URI) {
mongoose.connect(process.env.MONGODB_URI);
}
else {
mongoose.connect('mongodb://localhost/express-movies');
}
mongoose.connection.on('error', function(err) {
console.error('MongoDB connection error: ' + err);
process.exit(-1);
}
);
mongoose.connection.once('open', function() {
console.log("Mongoose has connected to MongoDB!");
});
Git commit the change and push to heroku:
git add -A
git commit -m "Updated DB connection code to use MongoLab when in Production"
git push heroku master
heroku ps
heroku open
Run the seeds file on the Heroku dyno:
heroku run node seeds.js
Test it out
heroku ps
heroku open