Skip to content

Instantly share code, notes, and snippets.

@avermeulen
Created June 11, 2019 12:25
Show Gist options
  • Save avermeulen/ba43eee156b50e60bf7470fc0780bc5a to your computer and use it in GitHub Desktop.
Save avermeulen/ba43eee156b50e60bf7470fc0780bc5a to your computer and use it in GitHub Desktop.

Tutor finder

This app help learners to find a tutor that you fits their pocket.

It's simple for tutors to get going. Select a subject to tutor, your hourly rate and your name and your ready to go.

This app will store it's data in PostgreSQL. And it will be an ExpressJS web app.

Create new folder called tutor-finder. Change into it. Open the folder in VS Code.

Install PostgreSQL

To install PostgreSQL follow these steps:

Create a database called my_products and username - coder with a password of pg123. Enter the password when prompted after executing the createuser command.

sudo -u postgres createdb tutor-finder;
-- sudo -u postgres createuser coder -P;

Now run psql as the postgres user:

sudo -u postgres psql;

Grant the coder user access to the tutor-finder database by running this command:

grant all privileges on database tutor-finder to coder;

Type in \q to exit psql as the postgres user.

Connect to your database using: psql -d tutor-finder

Setup up the database

To create the database in your local PostgreSQL do this.

First create the database: createdb tutor-finder

Create a folder called sql and create a file in there called create-tutor-table.sql.

In that file put the database script code to create the tutor table.

create table tutor (
	id serial not null primary key,
	full_name text not null,
	email text not null,
    subject text not null,
	hourly_rate decimal(10,2)
);

Connect to the tutor-finder database using psql the PostgreSQL command line client. Do this from your projects route folder. Not from the sql folder.

psql tutor-finder

Once in psql run the \dt command you will get a message stating Did not find any relations. - meaning that there are no databases in the tutor-finder database.

To create the tutor table in the databae run the create-tutor-table.sql script that we created earlier using this command.

\i sql/create-tutor-table.sql

You should see a message of CREATE TABLE.

Running the \dt command. You should see a list of the tables in the database. There should be one table the tutor reason.

Some SQL commands

Let's explore SQL now. Using SQL you can add, update, remove and find data in a SQL database.

To create a new tutor use an insert query like this:

insert into tutor (full_name, email, subject, hourly_rate) values ('Lindani Pani', '[email protected]', 'Mathematics', 45);

You can copy and paste this into the psql window and press enter. Note the semi-colon ; which executes the sql command.

insert into tutor (full_name, email, subject, hourly_rate) values ('Nkosi Ndlovu', '[email protected]', 'Mathematics', 40);

insert into tutor (full_name, email, subject, hourly_rate) values ('Thando Ntini', '[email protected]', 'Mathematics', 35);

You can also use a sql script file with insert statements. To do that create a file your sql folder called insert-tutors.sql and add insert statements on seperate lines.

Execute the script in psql using: \i sql/insert-tutors.sql

Add some 3 different tutors for Mathematics, Life Sciences and Economics. You can add for other subjects as well.

Find data using SQL

To see all the tutors in the database you can use a select query in psql:

select * from tutor;

To find all the tutors for a given subject you can adda where clause to your SQL:

select * from tutor where subject = 'Mathematics'; 

You can even check for math tutors how are cheaper than a given rate:

select * from tutor where subject = 'Mathematics' and hourly_rate < 50; 

You can also use a greater than or greater/less and equal signs - >, <, <= and >=

Updating a rate

To update a tutors rate you can use an update query:

update tutor set hourly_rate = 33.50 where id = 3;

You can even do increase all the mathematics tutor rates with 10%:

update tutor set hourly_rate = hourly_rate * 1.1 where subject = 'Mathematics';

Play around and see what other updates you can do.

Removing data

To remove a tutor from the database you can use a delete query.

delete from tutor where email = '[email protected]';

You can have a where clause on any column in the database. If a delete statement has no where clause it will delete all the entries in the database so be carefull.

Running SQL from NodeJS

So far all the SQL we wrote ran from psql the PostgreSQL command line database client.

Let's change that and run some SQL queries from NodeJS using mocha.

To do that we will need to initiate a NodeJS project using npm and install mocha and a NodeJS database driver for PostgreSQL.

Do this using these commands inside your tutor-finder folder.

npm init --y
npm install --save-dev mocha
npm install --save pg

Create a test folder in the tutor-finder folder and create a file called tutor-sql-test.js in there.

In your package.json file change the test command from:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },

to

"scripts": {
    "test": "mocha"
  },

You can now run your tests using npm test.

Put this code in the tutor-sql-test.js:

const assert = require("assert");

describe("Using the tutor SQL table from NodeJS", function(){
	
	it("should be able to run a select query", function(){
		assert.equal(1,2);
	});

	it("should be able to run an update query", function(){
		assert.equal(1,2);
	});

	it("should be able to run an insert query", function(){
		assert.equal(1,2);
	});

	it("should be able to run a delete query", function(){
		assert.equal(1,2);
	});
});

If you run this using npm test you should have 4 failing tests.

Running a select query from NodeJS

To run a select query on NodeJS from PostgreSQL you will need to import the PostgreSQL NodeJS driver like this.

const pg = require('pg');

To start using it you will need to do this:

Callback select block:

const pg = require("pg");
const Pool = pg.Pool;

const connectionString = process.env.DATABASE_URL || 'postgresql://coder:pg123@localhost:5432/tutor-finder';

const pool = new Pool({
    connectionString
});

pool.query("select * from tutor", function(err, results){
	if (err) {
		console.log(err)
	} else {
		console.log("This will print later");
		console.log(results.rows);
	}
});

console.log("This will print first");

This code is using a callback function. Calls to databases in NodeJS are asyncronyous. It's non blocking. Look at the console.log statements to see the flow of the code.

The code above can be changed to use Promises like this:

pool
	.query("select * from tutor")
	.then(function(results){
		console.log("This will print later");
		console.log(results.rows);
	})
	.catch(function(err){
		console.log(err)
	});
	console.log("This will print first");

But we will be using the async/await notation to run our code - it makes it easier to use asynchronous code in NodeJS.

Put the "Callback select block" piece of code into mocha in the should be able to run a select query test.

Remember to import the Postgres driver in your test:

const pg = require("pg");
const Pool = pg.Pool;

Connect to your database in your tests describe function:

const connectionString = process.env.DATABASE_URL || 'postgresql://coder:pg123@localhost:5432/tutor-finder';

const pool = new Pool({
    connectionString
});

Use the pool variables query function to connect to run your sql query.

You should see all the tutor entries in the database now.

But we would like to use async/await instead.

Change your code in the should be able to run a select query test too:

it("should be able to run a select query", function () {

		const results = await pool.query("select * from tutor");
		console.log(results.rows);
		// assert.equal(1,2);
	});

That's much simpler... but if you run the code it will fail with an error like this:

const results = await pool.query("select * from tutor");
		                      ^^^^
SyntaxError: Unexpected identifier

As you haven't added an async modifier to your it function

Change it too:

it("should be able to run a select query", async function () {
	// your code is still here		
});

Run it now! You should see all your tutors displayed on the screen now. Fix the test to have an assert that check how many rows are returned from the database.

Like this for example:

assert.equal(3, results.rows.length)

Running an insert query from NodeJS

You can insert data into your database from NodeJS using an insert query.

Try this to add a new tutor:

it("should be able to run an insert query", async function () {
	const tutorData  = ["Andy Phiri", "[email protected]", "Economics", 45];

	// ensure the tutor is not in the database
	await pool.query("delete from tutor where email = $1", [tutorData[1]]);

	// insert a new tutor
	await pool.query("insert into tutor (full_name, email, subject, hourly_rate) values ($1, $2, $3, $4)", tutorData);

	const results = await pool.query("select * from tutor where email = $1", [tutorData[1]]);
	assert.equal(1, results.rows.length);
});

Run a select query from psql to see if the new tutor is getting added.

You can extend your test to:

  • delete the tutor then
  • add it
  • and then check if it was added succussfully like this.

Update a tutors subject

Now lets write some code that can update a tutors Subject

	it("should be able to run an update query", async function () {
	
		// set tutor with id=3 subject to History
		const tutorData = ["History", 3];
		await pool.query("update tutor set subject = $1 where id = $2", tutorData);
		
		// test that it worked
		const results = await pool.query("select subject from tutor where id = $1", [3]);
		assert.equal("History", results.rows[0].subject);
	});

Deleting a tutor

To delete a tutor you will use a SQL delete query and you can add where clause the same as before.

Creating a web application

To add tutors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment