Skip to content

Commit

Permalink
Merge pull request #14 from bgveenstra/patch-1
Browse files Browse the repository at this point in the history
controller-doc-review
  • Loading branch information
tgaff committed Apr 2, 2016
2 parents 3d920d0 + cce0c8b commit e3f90a7
Showing 1 changed file with 65 additions and 19 deletions.
84 changes: 65 additions & 19 deletions docs/controllers_example.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@

#### Before Controllers

If you haven't seen this before you may be surprised to discover that the logic for every route doesn't have to be in server.js. If you think about it though, it's obvious that in large apps server.js would become very long and hard to work with. _yuck_
If you haven't seen this before, you may be surprised to discover that the logic for every route doesn't have to be in `server.js`. If you think about it, though, it's obvious that in large apps, server.js would become very long and hard to work with. _yuck_

#### Controllers and Resources

We're going to use the module pattern and create a module for each **controller** where we'll store all the route logic for that particular **resource**. A **resource** can be thought of as being related to the endpoints in your routes. For example, in Tunely we'll have a `/api/albums/:id` route. `albums` is a **resource** here and we'll give it it's own **controller**. You might later put `artists`, or `record_labels` in their own **controllers**.
We're going to use the module pattern to separate out some of the code that's currently in our server.js. Have you heard the term **resource**? A **resource** is just a type of data your app stores -- and it can be thought of as being related to the endpoints in your routes. For example, in Tunely we'll have a `/api/albums/:id` route. `albums` is a resource here. To take full advantage of the module pattern, we'll create a module for each resource where we'll store all the server's logic for interacting with that resource. This logic module will be called the **controller** for that resource. So each resource in your database will have its own **model** and its own **controller**. You might later add `artists` or `record_labels` and give each one its own **controller** and **model**.

#### Modules

You've already seen this pattern when using models!

1. We `export` the relevant objects from a file.
1. We `require` those other files in an `index.js` and re-`export` everything as an object.
1. When we need to use those objects we `require` the directory containing those files (which reads `index.js` and retrieves that object).
1. We `require` those other files in an `index.js` to group them and then re-`export` everything inside one object.
1. When we need to use those objects, we `require` the directory containing those files (this reads `index.js` and retrieves that combined controller object).

The key here is to realize that `module.exports` always starts as an empty object `{}`.

> If you `module.exports = { key: value }` you can export anything!
> If you `module.exports = { key: value }`, you can export anything!
Let's look at an example:

Expand Down Expand Up @@ -61,7 +61,7 @@ In the above `index.js` is exporting an object that looks like:
}
```

Anywhere we import `models/index` or even `models` we get that object.
Anywhere we import `models/index`, or even `models`, we get that object.

Let's take a look:

Expand All @@ -78,47 +78,90 @@ db.Author.find

#### Applying this to controllers

Let's refactor this `server.js` to use controllers:
Let's refactor `server.js` to use controllers. Here's our starting point:

```
```js
// server.js


app.get('/api/cards', function cardsIndex(req, res) {
// do index stuff
// get all cards from the database
db.Card.find({}, function(err, allCards) {
// add some error checking here!
// respond, sending all cards back
res.json(allCards);
});
}
app.post('/api/cards', function cardsCreate(req, res) {
// do post stuff
// make a new card with the form data from req.body
var newCard = new Card({
frontText: req.body.frontText,
backText: req.body.backText
});
}
app.get('/api/cards/:id', function cardsShow(req, res) {
// do show stuff
// pull card id out of the request
var cardId = req.params.card_id;
// get single card from the database
db.Card.findOne({_id: cardId}, function(err, thatCard) {
// add some error checking here!
// respond, sending all cards back
res.json(thatCard);
});
}
```
> aww check out those beautiful RESTful routes!
> aww, check out those beautiful RESTful routes!
##### New file structure
```
├── server.js
└── controllers
├── index.js
└── cards.js
└── models
├── index.js
├── quote.js
└── author.js
```
##### Refactor
```js
// controllers/cards.js

// send all card data back!
function index(req, res) {
// do index stuff
// get all cards from the database
db.Card.find({}, function(err, allCards) {
// add some error checking here!
// respond, sending all cards back
res.json(allCards);
});
}

// create a card!
function create(req, res) {
// do post stuff
// make a new card with the form data from req.body
var newCard = new Card({
frontText: req.body.frontText,
backText: req.body.backText
});
}

// send data for one card
function show(req, res) {
// do show stuff
// pull card id out of the request
var cardId = req.params.card_id;
// get single card from the database
db.Card.findOne({_id: cardId}, function(err, thatCard) {
// add some error checking here!
// respond, sending all cards back
res.json(thatCard);
});
}

var publicMethods = {
Expand All @@ -129,7 +172,8 @@ var publicMethods = {
module.exports = publicMethods;
```
Then in `index.js` we require and re-export.
Then, in `controllers/index.js`, we require and re-export.
> This step may seem odd right now, but when you have 15 controllers, you'll thank us.
```js
Expand All @@ -138,7 +182,7 @@ module.exports.cards = require('./cards');
module.exports.someOtherController = require('./someOtherController');
```
Finally in server.js we connect these together:
Finally in `server.js` we connect these together:
```js
// server.js
Expand All @@ -149,9 +193,11 @@ app.post('/api/cards', controllers.cards.create);
app.get('/api/cards/:id', controllers.cards.show);
```
![dancing semaphore man](https://media.giphy.com/media/rDroB384ydCvK/giphy.gif)
#### Wrap-up
Using this pattern it becomes clear where to find the logic for each route and your server.js file becomes much cleaner. It also starts guiding us down the path of using RESTful routes since we're assigning these typical names like index, show, create, etc. We can group by **resource** which makes it easier for future developers on the project to find what they need.
Using this pattern, it becomes clear where to find the logic for each route, and your `server.js` file becomes much cleaner. It also helps us start using some conventional names for RESTful routes: index, show, create, etc. We also group the logic by **resource**, which makes it easier for future developers on the project to find what they need.
Your `server.js` file is effectively now a router. When you work with other server architectures you will run into very similar patterns; knowing how this works will help you to adapt to other technologies you come across!
Your `server.js` file is effectively now a list of routes with the controller methods those routes use. When you work with other server architectures, you will run into very similar patterns. Knowing how this works will help you to adapt to other technologies you come across!

0 comments on commit e3f90a7

Please sign in to comment.