Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Look into having before/after methods for Controller routes #136

Open
zship opened this issue Jul 23, 2014 · 1 comment
Open

Look into having before/after methods for Controller routes #136

zship opened this issue Jul 23, 2014 · 1 comment
Milestone

Comments

@zship
Copy link
Contributor

zship commented Jul 23, 2014

Brought up in the Lavaca meeting: example given was doing authentication before routes execute.

@zship
Copy link
Contributor Author

zship commented Aug 6, 2014

Some communities call this Aspect-oriented programming. That wiki article is wordy, so here are some code examples from the Spring framework (Java). AOP "advice" is a way to have many functions run common code (another function) before or after they execute. This is easy in a language with first-class functions like JavaScript. Take one of our usual Controllers:

var HomeController = BaseController.extend({
  index: function(params, history) {
    var model = new Model();
    return this.view(null, HomeView, model);
  }
});

Add an authentication check the "regular" way:

var authenticationCheck = function() {
    if (!user.isAuthenticated()) {
        redirect('/login');
    }
};

var HomeController = BaseController.extend({
  index: function(params, history) {
    authenticationCheck();
    var model = new Model();
    return this.view(null, HomeView, model);
  }
});

Do the same thing AOP-style:

var authenticationCheck = function() {
    if (!user.isAuthenticated()) {
        redirect('/login');
    }
};

var HomeController = BaseController.extend({
  index: function(params, history) {
    var model = new Model();
    return this.view(null, HomeView, model);
  }
});

// redefine HomeController#index to achieve "before" advice
var originalIndexMethod = HomeController.prototype.index;
HomeController.prototype.index = function() {
    authenticationCheck();
    return originalIndexMethod.apply(this, arguments);
}

That isn't too useful as-is, but it makes more sense when you want to do an authentication check before every method, or just a small handful of them:

var BigController = BaseController.extend({
  index: function(params, history) { /* big function body */ },
  about: function(params, history) { /* big function body */ },
  contact: function(params, history) { /* big function body */ },
  admin: function(params, history) { /* big function body */ },
  journal: function(params, history) { /* big function body */ },
  stuffNoOneCanEverKnow: function(params, history) { /* big function body */ },
  secretsEveryoneKnowsAnyway: function(params, history) { /* big function body */ }
});

var authenticationCheck = function() {
    if (!user.isAuthenticated()) {
        redirect('/login');
    }
};

['admin', 'journal', 'stuffNoOneCanEverKnow'].forEach(function(name) {
    var originalMethod = BigController.prototype[name];
    BigController.prototype[name] = function() {
        authenticationCheck();
        return originalMethod.apply(this, arguments);
    };
});

AOP has its supporters and detractors just like anything else. The Wikipedia article talks a little bit about the pros and cons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant