Permalink
Browse files

before filter code and examples

  • Loading branch information...
1 parent a566c3b commit a35cfead9bb31d759ef5b1790930d2584e93634f @dantebronto committed Jan 26, 2011
View
@@ -17,10 +17,10 @@ post('/order', function(){
get('/haml', function(){
return {
template: 'index',
- print_date: function () {
+ printDate: function () {
return (new Date()).toDateString();
},
- current_user: {
+ currentUser: {
name: "Jean-Luc Picard",
bio: "Captain of the USS Enterprise"
}
@@ -40,7 +40,7 @@ get('/json', function(){
})
get('/redirect/?', function(request){
- return request.redirect('/haml')
+ request.redirect('/haml')
})
Picard.start()
@@ -8,8 +8,8 @@
.profile
.left.column{ id: 'this_is_an_id' }
- #date= "Stardate: #{print_date()}"
+ #date= "Stardate: #{printDate()}"
.right.column
- #name= "Name: #{current_user.name}"
- #title= "Title: #{current_user.bio}"
+ #name= "Name: #{currentUser.name}"
+ #title= "Title: #{currentUser.bio}"
@@ -1,10 +1,9 @@
require('../../lib/picard').globalize().start()
# Not much to see here. The only difference:
-# run with `coffee app.coffee`
+# compile or run with `coffee app.coffee`
-get '/', ->
- text: 'Hello Universe'
+get '/', -> 'Wicked short route'
get '/redirect/?', (env) ->
env.redirect('/')
View
@@ -0,0 +1,47 @@
+var Picard = require('../../lib/picard')
+
+// Filters are only available in Route Sets, for performance reasons
+
+Picard.routeSet('simple', function(){
+
+ var self = this
+
+ self.before(function(env){
+ env.foo = 'Foo' // set var on env for use later in filter chain or in main handler
+ return true // as long as you return something here, action will continue
+ })
+
+ self.before(function(env){
+ process.nextTick(function(){ // Simulate some async action,
+ env.filterDone() // call filterDone when complete.
+ })
+ })
+
+ self.get('/', function(env){ // After an async filter you'll need to call
+ env.onScreen('Hello, ' + env.foo + '!') // onScreen in your route handler (instead of returning)
+ })
+
+})
+
+Picard.routeSet('selective', function(){
+
+ this.before(/snappy/, function(env){ // can take RegExp or string as first argument
+ if ( env.cookie('session_id') || env.parsedUrl().query['session_id'] ){ // contrived example
+ return true // pass to the 'snappy_path'
+ } else {
+ env.redirect('/login')
+ return false
+ }
+ })
+
+ this.get('/snappy_path', function(env){
+ env.onScreen('Hello from the snappy path!') // After an async filter you'll need
+ }) // to call onScreen in your route handler
+
+ this.get('/login', function(){
+ return '<a href="/snappy_path?session_id=' + new Date().getTime() + '">fake login</a>'
+ })
+
+})
+
+Picard.start()
View
@@ -1,6 +1,6 @@
var Filter = {
before: function(matcher, cb){
- if ( typeof matcher == 'function' ){
+ if ( toString.call(matcher) == '[object Function]' ){
cb = matcher
matcher = '.*'
}
View
@@ -68,11 +68,11 @@ var RequestExtensions = {
return parsed
},
redirect: function(location){
- return {
+ this.onScreen({
status: 302,
headers: [[ 'Location', location ]],
body: '<a href="'+ location + '">' + location + '</a>'
- }
+ })
},
sendData: function(scope){
if ( !scope.body ) return
@@ -97,17 +97,17 @@ var RequestExtensions = {
this.handleException(ex)
}
},
- extractRouteParams: function(route, match_data){
+ extractRouteParams: function(route, matchData){
var i, l
- if ( match_data == null ){ return } else { match_data.shift() }
+ if ( matchData == null ){ return } else { matchData.shift() }
this.captures = []
for(i=0, l = route.keys.length; i < l; i++)
- this[route.keys[i]] = match_data.shift()
+ this[route.keys[i]] = matchData.shift()
- for(i=0, l = match_data.length; i < l; i++)
- this.captures[i] = match_data[i]
+ for(i=0, l = matchData.length; i < l; i++)
+ this.captures[i] = matchData[i]
},
pass: function(){
try {
@@ -173,20 +173,26 @@ var RequestExtensions = {
return headers
},
filterDone: function(){
- var filter = this.beforeFilters.shift(),
- res, req = this
+ var filter, res, req = this
- if ( filter ){
- res = filter.handler(req) // call the filter
+ if ( req.beforeFilters && req.beforeFilters.length > 0 ){
+ filter = req.beforeFilters.shift()
- if ( res == false ){
- req.handleNotFound()
- } else if ( toString.call(res) == '[object Object]' ){
- merge(req, res) // merge before filter result into env
- req.filterDone()
- } else if ( res != undefined ) { // not false or undefined, so keep going
- req.filterDone()
+ try {
+ res = filter.handler(req) // call the filter
+
+ if ( res === false ){
+ req.handleNotFound()
+ } else if ( toString.call(res) === '[object Object]' ){
+ merge(req, res) // merge before filter result into env
+ req.filterDone()
+ } else if ( res != undefined ) { // not false or undefined, so keep going
+ req.filterDone()
+ }
+ } catch(ex) {
+ req.handleException(ex)
}
+
} else { // we're done filtering
req.afterMainHandler(req.route.handler(req))
}
View
@@ -75,17 +75,17 @@ var Routes = {
var keys = []
if( toString.call(path) != '[object RegExp]' ){ // assume to be a String
- var full_route = '^'+path+'/?$',
- param_keys = path.match(/:[^/]+/g),
- regexp_as_string = full_route.replace(/([^\*]):[^/]+/g, '$1([^/]+)')
+ var fullRoute = '^'+path+'/?$',
+ paramKeys = path.match(/:[^/]+/g),
+ regExpAsString = fullRoute.replace(/([^\*]):[^/]+/g, '$1([^/]+)')
- if ( param_keys && path.match(/\*:\w+$/) )
- regexp_as_string = regexp_as_string.replace(/\*.+/, '(.+)')
+ if ( paramKeys && path.match(/\*:\w+$/) )
+ regExpAsString = regExpAsString.replace(/\*.+/, '(.+)')
- path = new RegExp(regexp_as_string)
- if( param_keys )
- for(var i=0, l = param_keys.length; i < l; i++)
- keys[keys.length] = param_keys[i].replace(/^:/, '')
+ path = new RegExp(regExpAsString)
+ if( paramKeys )
+ for(var i=0, l = paramKeys.length; i < l; i++)
+ keys[keys.length] = paramKeys[i].replace(/^:/, '')
}
var route = new Route({
View
22 spec.js
@@ -33,7 +33,12 @@ var SpecRunner = {
run: function(){
var self = this
spawn('ls', ['-1', __dirname + '/spec']).stdout.on('data', function(res){
- self.allSpecs = res.toString().split("\n")
+
+ if ( process.argv[2] != undefined ) // `node spec.js basic`
+ self.allSpecs = [process.argv[2]]
+ else
+ self.allSpecs = res.toString().split("\n")
+
SpecRunner.runSpecsFor(self.allSpecs.shift(), self.nextSpec)
})
},
@@ -42,18 +47,21 @@ var SpecRunner = {
if ( typeof spec != 'undefined' && spec != '' )
SpecRunner.runSpecsFor(spec, SpecRunner.nextSpec)
},
- runSpecsFor: function(appName, cb){
- var app, cmd = 'node', ext = 'js'
-
+ spawn: function(appName){
+ var cmd = 'node', ext = 'js'
+
if ( /coffee/.test(appName) )
ext = cmd = 'coffee'
- app = spawn(cmd, [__dirname + '/examples/' + appName + '/app' + '.' + ext])
-
+ return spawn(cmd, [__dirname + '/examples/' + appName + '/app' + '.' + ext])
+ },
+ runSpecsFor: function(appName, cb){
+ var app = SpecRunner.spawn(appName)
+
app.stdout.on('data', function(data){
data = data.toString()
var spec = __dirname + '/spec/' + appName
-
+
if ( /Picard boldly goes/.test(data) )
jasmine.executeSpecsInFolder(spec, function(runner, log){
app.kill('SIGHUP')
@@ -3,7 +3,7 @@ describe('can use coffeescript', function(){
it('should allow routes written in coffeescript', function(){
testReq('GET', '/', function(status, _, body){
expect(status).toEqual(200)
- expect(body).toMatch('Hello Universe')
+ expect(body).toMatch('Wicked short route')
asyncSpecDone()
})
asyncSpecWait()
@@ -16,5 +16,5 @@ describe('can use coffeescript', function(){
})
asyncSpecWait()
})
-
+
})
@@ -0,0 +1,34 @@
+describe('basic before filters', function(){
+
+ it('should pass data to the route handler', function(){
+ testReq('GET', '/', function(status, _, body){
+ expect(status).toEqual(200)
+ expect(body).toMatch('Hello, Foo!')
+ asyncSpecDone()
+ })
+ asyncSpecWait()
+ })
+
+})
+
+describe('advanced before filters', function(){
+
+ it('should honor onScreen calls from the before filters', function(){
+ testReq('GET', '/snappy_path', function(status, _, body){
+ expect(status).toEqual(302)
+ expect(body).toMatch('login')
+ asyncSpecDone()
+ })
+ asyncSpecWait()
+ })
+
+ it('should honor onScreen calls from the before filters', function(){
+ testReq('GET', '/snappy_path?session_id=123', function(status, headers, body){
+ expect(status).toEqual(200)
+ expect(body).toMatch('Hello from the snappy path!')
+ asyncSpecDone()
+ })
+ asyncSpecWait()
+ })
+
+})

0 comments on commit a35cfea

Please sign in to comment.