JavaScript Install and Use Sequelize CLI

Nick Hericks
Nick Hericks
Full Stack JavaScript Techdegree Graduate 20,644 Points

An updated guide for the outdated "Using SQL and Node.js with Sequelize" workshop

Because the content for this workshop is outdated, I struggled with it. In order to get my Sequelize blog exercise to work I put together the notes below. Hopefully others can benefit from it as well.

5 Answers

Nick Hericks
Nick Hericks
Full Stack JavaScript Techdegree Graduate 20,644 Points

Treehouse is aware that this Sequelize content is outdated and has stated that they're working on creating updated content (see Treehouse Content Roadmap).

Until the content is updated, along with the existing workshop videos and Sequelize docs, the steps and guidance below will hopefully be helpful for others that feel stuck and a bit lost with this workshop.

The intention of this guide is not to simply get people through the workshop and get on to the next course, but instead, the goal is to help others to better understand how to use Sequelize.

(Note: I'm running macOS)

Let's get started :)


SETUP

  1. Do not use workspaces for this exercise.
  2. Download files from first video.
  3. After downloading, use the files located in the sequelize_blog-start folder.
  4. Open the project in your text editor of choice.
  5. Create a .gitignore file and add node_modules (if you plan on using git)
  6. Create a README.md

INSTALL AND USE SEQUELIZE CLI (2nd video)

Run the following:

  • npm install
  • npm install --save pug
  • npm audit fix (To fix vulnerabilities. I did not fix the remaining 4-5 vulnerabilities as they required manual review or were potentially breaking changes.)
  • npm install --save sequelize
  • npm install --save sqlite3
  • npm install --save sequelize-cli
  • npx sequelize-cli init

In the /config/config.json file, replace everything with the following:

{
  "development": {
    "dialect": "sqlite",
    "storage": "development.db",
    "operatorsAliases": false
  },
  "test": {
    "dialect": "sqlite",
    "storage": "test.db",
    "operatorsAliases": false
  },
  "production": {
    "dialect": "sqlite",
    "storage": "production.db",
    "operatorsAliases": false
  }
}

To create first model, run the the following in the console:

npx sequelize-cli model:generate --name Article --attributes title:string,author:string,body:text

This will create a /models/article.js file which is a table representation. It maps your database columns to a JS object. Also, it creates a /migrations/xxxxxx-create-article.js file which represents a change to the model (table) which is used by the sequelize-CLI. (Migrations can be thought of as a commit or log of a change to the database.)

In order to update your database with the created model, you'll need to sync changes, which will be done automatically every time the server starts.

In the /bin/www file, find "server.listen(port)" and wrap it like below:

sequelize.sync().then(function(){
  server.listen(port);
});

In the /bin/www file, near the top of the file, require sequelize by adding:

var sequelize = require("../models").sequelize;

In the app.js file, change the view engine setup from 'jade' to 'pug'

app.set('view engine', 'pug');

In the 'views' directory, update all view files (10 total, including those in the 'articles' sub-directory) from the .jade file extension to the .pug file extension.

CREATING ENTRIES IN A TABLE (3rd video)

In the /routes/articles.js file, near the top of the file add:

var Article = require("../models").Article;

In the console, run:

npm start

Go to 'localhost:3000' in your web browser to view project.

In /routes/articles.js file, find the "Create a new article form" route and change "article: {}" to "article: Article.build()". The route should now be:

router.get('/new', function(req, res, next) {
  res.render('articles/new', {article: Article.build(), title: 'New Article'});
});

In /routes/articles.js file, find the "POST create article" and replace everything inside of it so that it now reads:

router.post('/', function(req, res, next) {
  Article.create(req.body).then(function(article) {
    res.redirect("/articles/" + article.id);
  });
});

In the console, restart the server by stopping it with 'Control + C' on Mac, then run:

npm start

Refresh browser page.

On the add new articles page in the browser, enter some test data into the title, author and body fields and hit enter. You should be taken to a page for a static article (since we're not retrieving it from the database yet).

INSTANCE METHODS (4th video)

In the /routes.articles.js file, delete the following:

var dateFormat = require('dateformat');

function publishedAt() {
  return dateFormat(this.createdAt, "dddd, mmmm dS, yyyy, h:MM TT");
}

function shortDescription(){ 
  return this.body.length > 30 ? this.body.substr(0, 30) + "..." : this.body;
}

In the /models/article.js file, replace everything in the file with the following:

'use strict';
var dateFormat = require('dateformat');

module.exports = function(sequelize, DataTypes) {
  var Article = sequelize.define('Article', {
    title: DataTypes.STRING,
    author: DataTypes.STRING,
    body: DataTypes.TEXT
  });

  // Article.someClassMethod = function() {};

  Article.prototype.publishedAt = function() {
    return dateFormat(this.createdAt, "dddd, mmmm dS, yyyy, h:MM TT");
  };

  Article.prototype.shortDescription = function() { 
    return this.body.length > 30 ? this.body.substr(0, 30) + "..." : this.body;
  };

  return Article;
};

RETRIEVING ENTRIES FROM A TABLE (5th video)

In the /routes/articles.js file, find the "GET individual article" route. Update it to be:

router.get("/:id", function(req, res, next){
  Article.findByPk(req.params.id).then(function(article){
    res.render("articles/show", {article: article, title: article.title});
  });
});

Be sure to use the .findByPk Sequelize function which has replaced the deprecated .findById function.

In the /routes/articles.js file, delete the 'articles' variable holding the static articles. Also delete the 'find' function just below the articles variable.

In the /routes/articles.js file, update the "GET articles listing" route so that it orders the results:

router.get('/', function(req, res, next) {
  Article.findAll({order: [["createdAt", "DESC"]]}).then(function(articles){
    res.render('articles/index', {articles: articles, title: 'My Awesome Blog' });
  });
});

UPDATING ENTRIES IN A TABLE (6th video)

In the /routes/articles.js file, update the "Edit article form" route to be:

router.get('/:id/edit', function(req, res, next){
  Article.findByPk(req.params.id).then(function(article) {
    res.render('articles/edit', {article: article, title: 'Edit Article'});
  });
});

In the /routes/articles.js file, update the "PUT update article" route to be:

router.put('/:id', function(req, res, next){
  Article.findByPk(req.params.id).then(function(article) {
    return article.update(req.body);
  }).then(function(article){
    res.redirect("/articles/" + article.id);    
  });
});

DELETING ENTRIES FROM A TABLE (7th video)

In the /routes/articles.js file, update the "Delete article form" route to be:

router.get('/:id/delete', function(req, res, next){
  Article.findByPk(req.params.id).then(function(article) {
    res.render('articles/delete', {article: article, title: 'Delete Article'});
  });
});

In the /routes/articles.js file, update the "DELETE individual article" route to be:

router.delete('/:id', function(req, res, next){
  Article.findByPk(req.params.id).then(function(article) {
    return article.destroy();
  }).then(function(){
    res.redirect("/articles");
  });
});

VALIDATION AND HANDLING ERRORS (8th video)

Nothing outdated here, follow all instructions in the video.

CELEBRATE! 🎉

...and then get back to it.

Daniel Gibson
Daniel Gibson
Full Stack JavaScript Techdegree Graduate 15,968 Points

Thanks Nick! Much needed as I was just stuck on this part.

Quick note, there is a small error in your code above: In the 3rd Video section:

In /routes/articles.js file, find the "POST articles listing" and replace everything inside of it so that it now reads:

router.post('/', function(req, res, next) {
  Article.create(req.body).then(function(article) {
    Res.redirect("/articles/" + article.id);
  });
};

This should actually say: In /routes/articles.js file, find the "POST create article" and replace everything inside of it so that it now reads:

router.post('/', function(req, res, next) {
  Article.create(req.body).then(function(article) {
    res.redirect("/articles/" + article.id);
  });
});

3rd line had a uppercase "R" in res.redirect, needs to be lowercase, and it was missing a bracket at the end of the code

Tobiasz Gala
Tobiasz Gala
Full Stack JavaScript Techdegree Student 23,513 Points

Also since pug is new jade you need to change files name from *.jade to *.pug in views folder and change 'view engine' to 'pug' in app.js file

Michael Chambers
Michael Chambers
Full Stack JavaScript Techdegree Graduate 28,199 Points

Nick Hericks, this is super helpful. I completed this course a couple of months ago and it drove me crazy. One thing I'm still uncertain about is how to pull up the sequelize cli help menu. The commands in the video do not work. For example, I'm trying to get to the help menu Andrew arrives at that provides details on generating models. I know model:create is now model:generate, but even if I use the suggested node_modules/.bin/sequelize help:model:generate command it shows up as an unknown argument. Any ideas?

Nick Hericks
Nick Hericks
Full Stack JavaScript Techdegree Graduate 20,644 Points

Hey Michael Chambers, I wasn't ever able to get the Sequelize cli help menu to work either. From what I understand the new version of Sequelize has a bug that currently prevents the help menu from working. More info in this thread: https://teamtreehouse.com/community/help-not-working

Jimmy Dorvilus
Jimmy Dorvilus
Full Stack JavaScript Techdegree Graduate 27,971 Points

Hi guys,
Typing npx sequelize --help will give you access to the help menu

hope that helped