Permalink
Browse files

added new LayoutResponse to simplify architecture

  • Loading branch information...
1 parent 1f55995 commit 71ecf6b560fa18061c7bac87720164daeb1df94d Seth Purcell committed Feb 1, 2012
Showing with 187 additions and 2 deletions.
  1. +1 −1 index.js
  2. +84 −0 lib/LayoutResponse.js
  3. +3 −1 lib/View.js
  4. +1 −0 lib/ViewRegistry.js
  5. +98 −0 testing/tests/LayoutResponseTest.js
View
@@ -29,7 +29,7 @@
var modules = ['App', 'Server', 'Stage', 'Request', 'Response',
'Redirect', 'FileResponse', 'Service',
- 'JsonResponse', 'BlobResponse', 'ViewResponse',
+ 'JsonResponse', 'BlobResponse', 'ViewResponse', 'LayoutResponse',
'ClientResponse', 'Resolver',
'Route', 'HttpClient', 'Browser', 'Cookie', 'Form',
'Session', 'SessionStore', 'View', 'ViewRegistry'];
View
@@ -0,0 +1,84 @@
+/*!
+ * Copyright (c) 2011 Sitelier Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Seth Purcell
+ * Date: 11/14/11
+ */
+
+"use strict";
+
+var ViewResponse = require('./ViewResponse').ViewResponse;
+var View = require('./View').View;
+
+var LayoutResponse = ViewResponse.extend(
+ /** @lends LayoutResponse */ {
+},
+/** @lends LayoutResponse# */{
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * @constructs
+ * @param view a View object or a view name
+ * @param model the view model object
+ * @param code optional HTTP status code
+ * @param layout the name of the layout view; defaults to 'layout'
+ */
+ init: function(view, model, code, layout) {
+
+ this._super(view, model, code);
+ this.layout = layout || 'layout';
+ },
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Injects the ability to render the view for this response. Even if this.view
+ * is already a renderable View, we need a ViewRenderer to resolve any
+ * references.
+ *
+ * @param renderer a ViewRenderer
+ */
+ setRenderer: function(renderer) {
+ this.renderer = renderer;
+ return this;
+ },
+
+ ///////////////////////////////////////////////////////////////////////////////
+ /**
+ * Writes the response body to the given stream.
+ *
+ * @param stream writable stream
+ */
+ sendBody: function(stream) {
+
+ // render the content view
+ var content = this.renderer.render(this.view, this.model);
+
+ // now render the layout
+ var result = this.renderer.render(this.layout, {
+ content: content,
+ child: this.model
+ });
+
+ stream.end(result, 'utf8');
+ }
+});
+
+exports.LayoutResponse = LayoutResponse;
View
@@ -79,7 +79,8 @@ var View = Class.extend(
///////////////////////////////////////////////////////////////////////////////
/**
* Registers the given view object or name on this View as a parent.
- *
+ *
+ * @deprecated because of the new LayoutResponse; this is unnecessarily general
* @param view
*
* @return object fluent
@@ -93,6 +94,7 @@ var View = Class.extend(
/**
* Returns this view's parent view.
*
+ * @deprecated because of the new LayoutResponse; this is unnecessarily general
* @return object|string
*/
getParent: function() {
View
@@ -159,6 +159,7 @@ var ViewRegistry = Class.extend(
}
// see if the view has a parent, and render that, too
+ // todo remove this stuff
var parent = v.getParent() || layout;
if (parent) {
@@ -0,0 +1,98 @@
+/*!
+ * Copyright (c) 2011 Sitelier Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Seth Purcell
+ * Date: 11/8/11
+ */
+
+"use strict";
+
+var testbench = require(__dirname + '/../TestBench');
+var MonkeyPatcher = require('capsela-util').MonkeyPatcher;
+var Pipe = require('capsela-util').Pipe;
+var mp = new MonkeyPatcher();
+
+var View = require('capsela').View;
+var LayoutResponse = require('capsela').LayoutResponse;
+
+module.exports["basics"] = {
+
+ tearDown: function(cb) {
+ mp.tearDown();
+ cb();
+ },
+
+ "test init w/name": function(test) {
+
+ var response = new LayoutResponse('my-view', {}, 701);
+
+ test.equal(response.view, 'my-view');
+ test.equal(response.layout, 'layout');
+ test.equal(response.statusCode, 701);
+ test.equal(response.getContentType(), 'text/html; charset=utf-8');
+
+ test.done();
+ },
+
+ "test init w/view": function(test) {
+
+ var mockView = {};
+ var response = new LayoutResponse(mockView, {}, 401, 'blueprint');
+
+ test.equal(response.view, mockView);
+ test.equal(response.statusCode, 401);
+ test.equal(response.layout, 'blueprint');
+ test.equal(response.getContentType(), 'text/html; charset=utf-8');
+ test.done();
+ },
+
+ "test sendBody": function(test) {
+
+ var vm = {};
+ var response = new LayoutResponse('my-view', vm, 701, 'bogans');
+ var pipe = new Pipe();
+
+ // test fluent interface
+ test.equal(response.setRenderer({
+ render: function(view, model) {
+
+ if (view == 'bogans') {
+ test.equal(model.child, vm);
+ return 'layout: ' + model.content;
+ }
+ else if (view == 'my-view') {
+ test.equal(model, vm);
+ return 'result';
+ }
+ }
+ }), response);
+
+ pipe.getData('utf8').then(
+ function(data) {
+ test.equal(data, 'layout: result');
+ test.done();
+ }
+ );
+
+ response.sendBody(pipe);
+ }
+};

0 comments on commit 71ecf6b

Please sign in to comment.