Skip to content

Instantly share code, notes, and snippets.

@drmikeh
Last active August 17, 2016 18:06
Show Gist options
  • Save drmikeh/6f3d2924e5ac51921d76225a46b55a6c to your computer and use it in GitHub Desktop.
Save drmikeh/6f3d2924e5ac51921d76225a46b55a6c to your computer and use it in GitHub Desktop.
Express Movies - MEN Stack Code Along

Express Movies - MEN Stack Code Along

Step 1 - Create the Project

mkdir express-movies
cd express-movies
express -e
npm install

Step 2 - Add Libraries

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/

Step 3 - Test it out

Edit package.json and replace node with nodemon

npm start

Step 4 - Setup Git Repo

git init
touch .gitignore
echo bower_components >> .gitignore
echo node_modules >> .gitignore
git add -A
git commit -m "Project setup completed."

Step 5 - Add Bootstrap and jQuery to our index.ejs

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>

Step 6 - WireUp Mongoose and Method Override

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'));

Step 7 - Test it out and Save Work

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."

Step 8 - Create Some Partials including a NavBar

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">&copy; 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

Step 9 - Create the INDEX Route for our Movies

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);

Step 10 - Create a Movie Mongoose Model and a Seeds file

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();
});

Step 11 - Use Mongoose Movie Model in INDEX route:

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 });
  });
});

Step 12 - Deploy to Heroku

12a. Create an Heroku Account

12b. Install the Heroku Toolbelt onto your computer:

Heroku Toolbelt

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment