1

I want to do a basic editing of data stored in the database (mongoDB). Here is what I've done:

angular service

createReview(review) {

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');

    this.http.post('http://localhost:3000/api/reviews', JSON.stringify(review), { headers: headers })
      .subscribe(res => {
        console.log(res.json());
      });

  }
editReview(review) {

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');
    this.http.post('http://localhost:3000/api/reviews', JSON.stringify(review), { headers: headers })
      .subscribe(res => {
        console.log(res.json());
      });
  }

deleteReview(id) {

this.http.delete('http://localhost:3000/api/reviews/' + id).subscribe((res) => {
  console.log(res.json());
});

}

in server.js

// Set up
var express = require('express');
var app = express(); // create our app w/ express
var mongoose = require('mongoose'); // mongoose for mongodb
var ObjectId = require('mongodb').ObjectID; // objectID
var morgan = require('morgan'); // log requests to the console (express4)
var bodyParser = require('body-parser'); // pull information from HTML POST (express4)
var methodOverride = require('method-override'); // simulate DELETE and PUT (express4)
var cors = require('cors');

// Configuration
mongoose.connect('mongodb://localhost/data');

app.use(morgan('dev')); // log every request to the console
app.use(bodyParser.urlencoded({ 'extended': 'true' })); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(methodOverride());
app.use(cors());

app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header('Access-Control-Allow-Methods', 'DELETE, PUT');
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

// Models
var Review = mongoose.model('Review', {
    title: String,
    description: String,
    rating: Number
});

// Routes

// Get reviews
app.get('/api/reviews', function(req, res) {

    console.log("fetching reviews");

    // use mongoose to get all reviews in the database
    Review.find(function(err, reviews) {

        // if there is an error retrieving, send the error. nothing after res.send(err) will execute
        if (err)
            res.send(err)

        res.json(reviews); // return all reviews in JSON format
    });
});


// create review and send back all reviews after creation
app.post('/api/reviews', function(req, res) {
    if (req.params.review_id == undefined) {
        console.log("creating review");

        // create a review, information comes from request from Ionic
        Review.create({
            title: req.body.title,
            description: req.body.description,
            rating: req.body.rating,
            done: false
        }, function(err, review) {
            if (err)
                res.send(err);

            // get and return all the reviews after you create another
            Review.find(function(err, reviews) {
                if (err)
                    res.send(err)
                res.json(reviews);
            });
        });
    } else {
        console.log("editing review")
        var query = ObjectId(req.params.review_id);

        // update a review, information comes from request from Ionic
        Review.findOneAndUpdate(query, {
            title: req.body.title,
            description: req.body.description,
            rating: req.body.rating,
            done: false
        }, function(err, review) {
            if (err)
                res.send(err);

            // get and return all the reviews after you create another
            Review.find(function(err, reviews) {
                if (err)
                    res.send(err)
                res.json(reviews);
            });
        });
    }
});

// delete a review
app.delete('/api/reviews/:review_id', function(req, res) {
    console.log("deleting review");
    Review.remove({
        _id: req.params.review_id
    }, function(err, review) {

    });
});


// listen (start app with node server.js) ======================================
app.listen(3000);
console.log("App listening on port 3000");

Creating a new review works just fine and also deleting a review. But when it comes to editing I get the undefined error from req.params.review_id in the app.post function in server.js. I'm sure I'm not doing this in a proper way. How to do an update of data using these libraries and frameworks?

Melchia
  • 22,578
  • 22
  • 103
  • 117
  • Clearly you are trying to fetch the review_id from params but you are not passing it in params as you are passing in delete call. either you modify the post call with /:review_id or you try to get review_id from req.body._id or whatever parameter you are using. Put a console.log to see what values you get for req.params and req.body – Rahul Kumar Aug 03 '17 at 09:51
  • this is the weird thing both req.params and req.body return empty object. Also when I give /:review_id as param it will not work when I create a new review – Melchia Aug 03 '17 at 09:53

1 Answers1

0

As mentioned in the comments, you use a parameter, which is not defined in the route of your express application.

You can make the parameter optional ( will work with create and edit ), by writing your route definition as :

app.post('/api/reviews/:review_id?', function(req, res) {
  /* .... */
} );

Keep in mind that following a proper REST architecture, you should separate the edit of an entity in a PUT request.

app.post( '/api/reviews', function( req, res ) { /** Handle Create */ } );
app.put( '/api/reviews/:review_id', function( req, res ) { /** Handle Edits */ } );
drinchev
  • 19,201
  • 4
  • 67
  • 93
  • 1
    According to this website put is to create and post is to edit. https://www.tutorialspoint.com/nodejs/nodejs_restful_api.htm – Melchia Aug 03 '17 at 16:16
  • https://stackoverflow.com/questions/630453/put-vs-post-in-rest it's only for cases when you ( the client ) define the identification of that entity. That happens rarely. Usually and in your case as well the server does that. – drinchev Aug 03 '17 at 16:38