Created
January 11, 2018 09:44
-
-
Save rob137/dcc044fd9eebfa25fd98fe0c1c35cac9 to your computer and use it in GitHub Desktop.
Thinkful Back-end Notes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Connect to the database, | |
then start the server, | |
then seed the database with test data, | |
then make a request to the API, | |
then inspect the response, | |
then inspect the state of the database. | |
function doMyTest() { | |
let db, server; | |
return connectToDb // Note that connectToDb isn't defined... | |
//Connect to the database, | |
.then(_db => { | |
db = _db | |
return startServer() | |
}) | |
//then start the server, | |
.then(_server => { | |
server = _server; | |
return seedData(db); | |
}) | |
//then seed the database with test data, | |
.then(() => { | |
return makeTestRequestToApi(server); | |
}) | |
//then make a request to the API, | |
.then(response => { | |
// do stuff to inspect response object | |
return queryDb() | |
}) | |
//then inspect the response, | |
.then(queryResult => { | |
// inspect query result | |
}) | |
//then inspect the state of the database. | |
.catch(error => { | |
// do something about the error | |
}); | |
} | |
// The above takes the form: | |
function doStuff() { | |
return doSomething // Note that doSomething isn't defined... | |
.then(function() { | |
[some stuff] | |
}) | |
.then(function() { | |
}).then( | |
[etc..] | |
); | |
} | |
// bad version: | |
function doMyTest(done) { | |
connectToDb(startServer(seedData(makeTestRequestToApi(inspectResponse(inspectDb(done)))))); | |
} | |
THE SERVER MODEL: | |
_________________________________________ | |
| | Server-side Programming is about: | |
| Server | Routing (requests to handlers) | |
| ['back-end'] | Data Persistence | |
| _______________ | Business Logic | |
| | | | Security | |
| | Database | | Software Testing | |
| | [files] | | DevOps | |
| | [API data] | | | |
| | | | | |
| |_______________| __________ | | |
| | | | | | |
| | | Static | | | |
| ______|_______ | Assets | | | |
| | | | | | | |
| | (Optional | | | | | |
| | Middleware) | | - HTML | | | |
| | Request | | - CSS | | | |
| | Handler |----| - JS | | | |
| | ______ | | - etc | | | |
| | | | | |__________| | | |
|____|___| PORT |___|_____________________| | |
|______| **Status codes in responses: | |
1xx - Informational | |
2xx - Success (200 is HTTP response default) | |
^ | 3xx - Redirection | |
| | 4xx - Client error | |
HTTP | | Response** 5xx - Server error | |
request*| | | |
| v | |
*Request verbs: (In Express:) | |
_______________ GET* ie 'read' app.get | |
| | HEAD app.head | |
| Client | POST* ie 'create' app.post | |
| ['front-end'] | PUT* ie 'replace' app.push | |
|_______________| DELETE* app.delete | |
CONNECT app.connect | |
OPTIONS app.options | |
TRACE app.trace | |
PATCH* ie 'update' | |
|____________________________________________________________| | |
| | |
['fullstack'] | |
The key parts of a modern server app: | |
- A way to listen for HTTP requests over a port: app.listen | |
- A way to inspect and interact with HTTP requests and responce objects: /public | |
- A way to route HTTP requests from clients to the right request handlers: app.get | |
- A way to serve static assets to client browsers: app.use(express.static('public')) | |
- A way to serve data to clients: app.get('/address', (req, res) =>) {} | |
To serve static assets, you need: | |
// load express and create your app | |
const express = require('express'); | |
const app = express(); | |
// set up your folder 'public' for static assets | |
app.use(express.static('public')); | |
// set up a response to get requests from clients | |
app.get("/", (request, response) => { | |
response.sendFile(__dirname + '/views/index.html'); | |
}); | |
// tell your server to start listening on a port | |
app.listen(process.env.PORT, () => { | |
console.log('Your app is listening on port ${process.env.PORT}'); | |
}); | |
"It's possible to set up more than one static folder." | |
https://www.example.com:8080/catpics/cats.html?name=value&foo-bar#anchor | |
____ _ _____ _ ___ _____ _______ _________________ _____ | |
| | | | | | | | | | |
Scheme | Domain | Port | File Querystring Fragment | |
(protocol) | | File (hash) | |
| Top level path | |
Sub-domain domain | |
- Go over difference between promises/callbacks/observables and get back to LM with any questions... | |
'REST API' stands for Representational State Transfer Application Programming Interface... | |
RESTful APIs expose resources through URLs. | |
The industry convention: endpoints are _nouns_ (e.g. /users/) and HTTP methods are _verbs_ (GET, POST, DELETE, PATCH, PUT etc) | |
'CRUD' stand for the four most common REST API operations: | |
_C_reating new resources. (POST) | |
_R_eading existing resources. (GET) | |
_U_pdating resources. (PUT) | |
_D_eleting resources. (DELETE) | |
Make APIs 'thin' - as far as possible, put the necessary conditional logic in your models instead. | |
When routing becomes at all complicated in server.js, use Express to create separate router files for each '/address'. This is called 'modularisation'. | |
TYPICAL COMMANDS TO START OWN WEB DEVELOPMENT PROJECT | |
mkdir [folder] && cd [folder] | |
npm init // prepare basic suite of packages | |
git init | |
echo "node_modules" > .gitignore // tell git to ignore node_modules | |
git add .gitignore // tell git to ignore node_modules | |
git add package.json | |
git commit -m 'initial commit' | |
npm test // run mocha/chai tests | |
nodemon server.js // run server | |
heroku create // setup heroku server | |
git push heroku master // push files to heroku server | |
heroku open // open app in browser | |
heroku logs --tail // show logs! | |
Heroku allows you to _deploy_ an app. Allows you to host. | |
TYPICAL COMMANDS TO CLONE WEB DEVELOPMENT PROJECT | |
Create reposititory on GitHub. | |
CD to folder on local. | |
git init | |
git add (any file) | |
git commit -m 'initial commit' | |
git remote set-url origin ___ [ssh address from repository on Github] | |
git push | |
npm install // download necessary dependencies | |
nodemon server.js // run server | |
REQUIREMENTS FOR BLOG API | |
Your app should support the four CRUD operations for a blog posts resource. | |
GET and POST requests should go to /blog-posts. | |
DELETE and PUT requests should go to /blog-posts/:id. | |
Use Express router and modularize routes to /blog-posts. | |
Add a couple of blog posts on server load so you'll automatically have some data to look at when the server starts. | |
Mocha: test framework for unit testing. | |
after npm init: | |
npm install mocha --save-dev | |
"Note that, by default, Mocha recusively looks for .js files in a 'test' folder. By convention, we name our test files with lowercase, dash-separated text beginning with test-." | |
Chai: test framework for integration testing. | |
Try deploying a project on Heroku to help you remember how it all works. | |
Mongo: | |
mongod // in one tab to init mongo | |
mongo // in another tab to init mongo console | |
db | |
show dbs | |
use somedatabase // switch to a database (eg somedatabase) | |
db.getCollectionNames() // Show collections in current database | |
db.restaurants.findOne() // Show a document in a collection. (eg restaurants) | |
db.restaurants.insertOne(myRestaurant) // add document to collection (eg myRestaurant to restaurants) | |
db.restaurants.insertMany([arrayofrestaurants]) | |
db.restaurants.insert(whatever) // will inset 1x object or arr, depending on what you give it | |
db.myCollection.find() // returns all results in collection (eg myCollection) | |
// .find returns a _cursor_ object | |
db.restaurants. | |
find({borough: "Manhattan"}, {_id: 1, name: 1, address: 1}). | |
sort({name: 1}). | |
limit(5); | |
// find within the restaurants collection: { key/value details }; sort by name; show first 5 results | |
// to find a document by its id: | |
var someId = ObjectId("59074c7c057aaffaafb0dcc1"); | |
db.restaurants.findOne({_id: someId}); | |
// to update an object: | |
// find an obj and get its id: | |
var objectId = db.restaurants.findOne({}, {_id: 1})._id; | |
// use the id to update with '$' | |
db.restaurants.updateOne( | |
{_id: objectId}, | |
{$set: {name: "Foo Bar"}} | |
); | |
// to see the changes | |
db.restaurants.findOne({_id: objectId}); | |
// replaceOne works the same way as updateOne. Fully replaces document. | |
db.restaurants.replaceOne( | |
{_id: objectId}, | |
{name: "Yummo's"} | |
); | |
// deleting: | |
.deleteOne | |
.deleteMany | |
db.myCollection.remove() // note that it defaults to deleting all documents that meet criteria | |
// so use | |
db.restaurants.remove({_id: objectId}); // using id ensures you only remove a single document | |
Exercises: | |
Get all | |
Find the command that retrieves all restaurants. | |
db.restaurants.find() | |
Limit and sort | |
Find the command that makes the first 10 restaurants appear when db.restaurants is alphabetically sorted by the name property. | |
db.restaurants. | |
find(). | |
sort({name: 1}). | |
limit(10) | |
Get by _id | |
Retrieve a single restaurant by _id from the restaurants collection. This means you'll first need to get the _id for one of the restaurants imported into the database. | |
var exampleId = db.restaurants.findOne({}, {_id: 1})._id; | |
db.restaurants.findOne({_id: exampleId}); | |
Get by value | |
Write a command that gets all restaurants from the borough of "Queens". | |
db.restaurants.find({borough: "Queens"}); | |
Count | |
Write a command that gives the number of documents in db.restaurants. | |
db.restaurants.count() | |
Count by nested value | |
Write a command that gives the number of restaurants whose zip code value is '11206'. Note that this property is at document.address.zipcode, so you'll need to use dot notation to query on the nested zip code property. | |
db.restaurants.find({"address.zipcode": "11206"}).count(); | |
Delete by id | |
Write a command that deletes a document from db.restaurants. This means you'll first need to get the _id for one of the restaurants imported into the database. | |
var exampleId = db.restaurants.findOne()._id; | |
db.restaurants.remove({"_id": exampleId}); | |
Update a single document | |
Write a command that sets the name property of a document with a specific _id to 'Bizz Bar Bang'. Make sure that you're not replacing the existing document, but instead updating only the name property. | |
var exampleId = db.restaurants.findOne()._id | |
db.restaurants.updateOne( | |
{"_id": exampleId}, | |
{$set: {"name": "Bizz Bar Bang"}} | |
); | |
Update many documents | |
Uh oh, two zip codes are being merged! The '10035' zip code is being retired, and addresses with '10035' will now fall under the '10036' zip code. Write a command that updates values accordingly. | |
var oldZipcodeRestaurants = db.restaurants.find({"address.zipcode": "10035"}); | |
db.restaurants.update ( | |
{"address.zipcode": "10035"}, | |
{$set: {"address.zipcode": "10036"}}, | |
{"multi": "true"} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment