In my previous blog post we went over creating an Ember project with Node or iojs.

To keep it simple we created an Express application with only one route that directed everything to our public/index.html. The index.html was the compiled Ember.js route.

Dan Hutchinson in the comments pointed out that we could have also created an Ember server and used the proxy command so all XHR requests would be sent to the Node server. Something like this.

$ ember server --proxy http://127.0.0.1:3000
$ node server.js //listening port 3000

The Ember server is running on port 4200 with a proxy to the Node server running on port 3000. This works fine and is a great way to test. Later on you can compile it if needed.

In this tutorial we'll add a connection to a MongoDB database and create a simple REST service to get and post quotes. You can follow along on Github if you like. (The Ember project is not included yet, only the Node server)

Setup

We left off from the last post with a working Node Express server. We'll continue from there.

Before we begin we'll need to make sure we have mongoDB installed. After this is done we can install mongoose. This will allow us to interface to our mongoDB database in Node.

$ npm install mongoose --save 
$ npm install body-parser --save

In addition we'll need the middleware body-parser. This will help us parse different type of response formats from and to our Node server.

Node Server File

Here is the new server.js file with comments. (We are using Express 4.12)

// server.js

// modules =================================================
var express        = require('express');  
var app            = express();  
var bodyParser     = require('body-parser');



// set our port
var port = process.env.PORT || 3000;

// set up mongoose, assume locally installed
var mongoose   = require('mongoose');  
mongoose.connect('mongodb://localhost/RESTServer');

// set the static files location for our Ember application
app.use(express.static(__dirname + '/public'));

//bodyParser Middleware to allow different encoding requests
app.use(bodyParser.urlencoded({ extended: true }));  
app.use(bodyParser.json());       // to support JSON-encoded bodies


//Routes API
var router = express.Router();  
app.use('/', router);  
require('./app/routes')(router); // configure our routes

// startup our app at http://localhost:3000
app.listen(port);


// expose app
exports = module.exports = app;

There are a few changes from our last post. We've included the bodyParser as well as Mongoose which will talk to our local MongoDB database. We are now using the Express router to setup our routes.

Directory Structure

The directory structure will look like this.

├── api
│   └── quote.js
├── app
│   └── routes.js
├── models
│   └── quote.js
├── package.json
├── TestProject 
├── public  
└── server.js

The api folder will hold our logic to add and retrieve posts. The models.js file shows the model for our quote schema. The TestProject folder holds our Ember.js application and the public folder is where the compiled Ember project resides.

Model

Let's take a look at this first.

// models/quote.js

var mongoose = require('mongoose');  
var Schema = mongoose.Schema;

var QuoteSchema = new Schema({

    quote: String,
    author: String
});


module.exports = mongoose.model('Quote', QuoteSchema);

All we are doing here is following the proper schema setup for mongoose and exporting it out as a module. The schema entails just a quote and an author.

API

We want to be able to add new quotes and retrieve them if needed. Let's take a look at that.

// api/quote.js

var Quote = require('../models/quote');

module.exports.getAllQuotes = function(req, res) {  
    Quote.find(function(err, quotes) {
        if (err) {
            res.send(err);
        }
        res.json({quotes: quotes});
    });
};

module.exports.addQuote = function(req,res) {  
    var quote = new Quote(req.body.quote);
    quote.save(function(err) {
        if (err) {
            res.send(err);

        }
        res.json({quote: quote});
    });
};

This is a little more complicated. Once again we'll use module exports to create addQuote and getAllQuotes. getAllQuotes uses the Quote object which is the mongoose schema we created earlier. We have a lot of different queries available to us. This will find all the quotes and then display the response in json. addQuote will save the quote to the MongoDB database.

Router

Everything is in place we can now take a peek at the router.

// app/router.js

 var quotes = require('../api/quote');
 module.exports = function(router) {


        router.route('/quotes').post(function(req, res) { console.log(req.body); quotes.addQuote(req,res); })
                              .get(function(req,res) { quotes.getAllQuotes(req,res) });
        router.route('*').get(function(req, res) {
            res.sendfile('./public/index.html'); // load our public/index.html file

        });

};

These routes are similar to what we had before except now we are using the router object. We have a new quotes route that executes the getAllQuotes module that we created earlier for get requests. If the agent connects with a post request then we send them to the addQuote module. The default route remains the same.

Testing Out Node Server

Before we move on let's test this with Postman! Postman is a simple tool to help send different requests to a server.

First we'll start the server

$ node server.js

We'll send a quote to the server. (FYI there seemed to be an issue with Postman sending a Content-Type application/json to the server so I had to specifically set that in the headers for this to work!)

We sent over this json message.

{"quote":{"quote":"If it is to be it's up to me!","author":"Unknown"}}

You could always just use the curl command as well.

$ curl -d '{"quote":{"quote":"You know me!","author":"Unknown"}}' -H "Content-Type: application/json" http://localhost:3000/quotes

We received a positive response so everything should be working.

Ember Setup

Since we have everything setup in our server let's see if we can get Ember working with it now. Once again we'll assume you're using the old Ember project that we created in the last post. If not that's OK, all you need to do is create a new project.

Setup

Before we begin let's create a few files and setup our CSP.

// config/environment.js
...
    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    },
    contentSecurityPolicy: {
              'default-src': "'none'",
              'script-src': "'self' 'unsafe-inline' 'unsafe-eval'",
              'font-src': "'self'",
              'connect-src': "'self' http://localhost:3000",
              'img-src': "'self'",
              'report-uri':"'localhost'",
              'style-src': "'self' 'unsafe-inline'",
              'frame-src': "'none'"
          }
  };

The above CSP will allow us to connect to the Node server running on port 3000.

$ ember g resource quote quote:string author:string

This will generate our route, model and template for us. When it generates the model it will populate the DS.attr for us for quote and author.

It's worth noting that we many have issues in the future since now we have a quote route using Ember and a quotes route in our Node server. For now this is OK, however in future posts I might just set all our REST node server routes to /api so it won't conflict.

$ ember g serializer application 

We'll need to create a serializer so Ember data knows what the primary key is. It defaults to id however since MongoDB defaults to _id so we need to change it.

// app/serializers/application.js

import DS from 'ember-data';

export default DS.RESTSerializer.extend({  
    primaryKey: '_id'
});

Route

Our route is very simple, it just retrieves all the quotes.

import Ember from 'ember';

export default Ember.Route.extend({  
    model: function() {
        return this.store.find('quote');
    }
});

Template

We should have everything in place to display our posts!

Quotes!<br/>  
{{#each quote in model}}
Quote: {{quote.quote}}<br/>  
Author: {{quote.author}}<br/>

{{/each}}

The each block will iterate through all the quotes sent from our model.

That should be it for Ember. The model is already created so we shouldn't have to worry about that.

Putting it all together

First we'll run both the Node and Ember server together, then we'll build Ember into our public folder.

$ node server.js
$ ember server --proxy http://127.0.0.1:3000 

This should allow us to check to see if everything is working. If everything is working http://localhost:4200/quote should show a list of quotes we added.

If that's working we can go ahead and build.

$ ember build --environment=production --output-path=../public/

This is once again assuming the Ember application is in the same folder as the Node server. If all is well we can just run the application server. I created a Github for this project. You'll need to create the Ember project separately but this should get you started.

Future

Now that we've been able to get our application talking to a MongoDB database we can now look into doing some more things. For example, deleting and editing quotes. Or retrieving individual quotes. I'll be investigating that in the future.

Thanks to Connor for his great guide and Scotch.IO for their MEAN stack tutorial. Both of which helped me out in writing this.

Questions? Leave a comment below!

Image Credit to MongoDB