2

I'm working on my first nodejs/backbone project. What I need to do is to extend user model api with additional methods. As REST uses universal post/get/put request, how do you extended backbone model with other api calls (ie. block user account where I don't want to update user and make /user/deactivate url)?

I can take ugly routes, but I looking for the "right way" from pros.

My backbone model

define(["jquery", "backbone"],
function($, Backbone) {
    var User = Backbone.Model.extend({
        urlRoot: '/user',

        defaults: {
            username: '',
            password: '',
            email: ''
        }
    });
    return User;
}
);

My nodejs "router"

    app.put('/user', userController.register);
    app.post('/user', userController.update);
    app.get('/user', userController.list);
    app.delete('/user', userController.delete);
Jon Miles
  • 9,605
  • 11
  • 46
  • 66
spamec
  • 301
  • 1
  • 5
  • 15

1 Answers1

2

Why not add block and deactivate attributes to your model, then just use standard REST / CRUD API calls.

Then your actions block and deactivate would just be standard model updates, with logic to handle blocked and active model states in your API methods.

define(["jquery", "backbone"],
function($, Backbone) {
    var User = Backbone.Model.extend({
        urlRoot: '/user',

        defaults: {
            username: '',
            password: '',
            email: '',
            blocked: false,
            active: true
        },

        block: function () {
            this.set('blocked', true);
            this.save();
        },

        deactivate: function () {
            this.set('active', false);
            this.save();
        },

    });
    return User;
}
);

EDIT - Based on your comment, the need to distinguish between updates

If you need to distinguish between field updates on the server, in order to run route specific validation for example. Then you're probably going to need to call custom routes for each specific action. A neat way of doing this would be to override the url during the call to save the model.

An updated model example.

define(["jquery", "backbone"],
function($, Backbone) {
    var User = Backbone.Model.extend({
        urlRoot: '/user',

        defaults: {
            username: '',
            password: '',
            email: '',
            blocked: false,
            active: true
        },

        block: function () {
            this.set('blocked', true);
            this.save(this, { url: '/user/block' });
        },

        deactivate: function () {
            this.set('active', false);
            this.save(this, { url: '/user/deactivate' });
        },

    });
    return User;
}
);

Then you would have the following routes

app.put('/user', userController.register);
app.post('/user', userController.update);
app.get('/user', userController.list);
app.delete('/user', userController.delete);
app.post('/user/block', userController.block);
app.post('/user/deactivate', userController.deactivate);
Jon Miles
  • 9,605
  • 11
  • 46
  • 66
  • Got the point, but this means that all of my "custom api methods" would point to "app.post('/user'..." route. This causes, that on the server side I have one entry point for multiple scenarios/scopes. Example - user email update, password change (with double field confirmation) and user deactivation will just post different fields to the same api method (without explicit meaning). – spamec Jan 20 '14 at 14:25
  • Then you could pass the route you want to hit as an option in model save e.g. this.save(this, { url: '/user/block' }) – Jon Miles Jan 20 '14 at 14:42