Permalink
Browse files

Merge branch 'master' into serverportfailure

  • Loading branch information...
2 parents e2f0753 + 8b543db commit 7f93697608fba239ae1fe2f598bbfeaa6019c0bb @MiguelMadero committed Oct 9, 2012
Showing with 24,752 additions and 212 deletions.
  1. +1 −0 .gitignore
  2. +33 −12 bin/cli.js
  3. +12 −0 changelog.md
  4. +5 −2 deps/templato/lib/engines/ejs.js
  5. +5 −2 deps/templato/lib/engines/handlebars.js
  6. +5 −2 deps/templato/lib/engines/jade.js
  7. +4 −2 deps/templato/lib/engines/mustache.js
  8. +72 −0 docs/1-architecture.md
  9. +110 −0 docs/2-router.md
  10. +208 −0 docs/3-controllers.md
  11. +422 −0 docs/4-models.md
  12. +317 −0 docs/5-templates.md
  13. +83 −0 docs/6-CLI.md
  14. +3 −3 examples/todo_app/app/controllers/todos.js
  15. +1 −5 examples/todo_app/config/init.js
  16. +0 −60 examples/todo_app/lib/model_adapters/todo.js
  17. +6 −14 examples/todo_app_coffee/app/controllers/todos.coffee
  18. +0 −5 examples/todo_app_coffee/app/models/todo.coffee
  19. +3 −6 examples/todo_app_coffee/config/development.coffee
  20. +15 −0 examples/todo_app_coffee/config/development.coffee.mongo
  21. +0 −5 examples/todo_app_coffee/config/init.coffee
  22. +1 −1 lib/app.js
  23. +1 −1 lib/config.js
  24. +0 −31 lib/i18n/index.js
  25. +3 −5 lib/init/i18n.js
  26. 0 {site → site-old}/css/bootstrap.css
  27. 0 {site → site-old}/css/bootstrap.min.css
  28. 0 {site → site-old}/css/bootstrap.min.responsive.css
  29. 0 {site → site-old}/css/bootstrap.responsive
  30. 0 {site → site-old}/docs.html
  31. 0 {site → site-old}/features.html
  32. 0 {site → site-old}/img/glyphicons-halflings-white.png
  33. 0 {site → site-old}/img/glyphicons-halflings.png
  34. 0 {site → site-old}/index.html
  35. 0 {site → site-old}/js/bootstrap.js
  36. 0 {site → site-old}/js/bootstrap.min.js
  37. 0 {site → site-old}/js/google-code-prettify/lang-apollo.js
  38. 0 {site → site-old}/js/google-code-prettify/lang-clj.js
  39. 0 {site → site-old}/js/google-code-prettify/lang-css.js
  40. 0 {site → site-old}/js/google-code-prettify/lang-go.js
  41. 0 {site → site-old}/js/google-code-prettify/lang-hs.js
  42. 0 {site → site-old}/js/google-code-prettify/lang-lisp.js
  43. 0 {site → site-old}/js/google-code-prettify/lang-lua.js
  44. 0 {site → site-old}/js/google-code-prettify/lang-ml.js
  45. 0 {site → site-old}/js/google-code-prettify/lang-n.js
  46. 0 {site → site-old}/js/google-code-prettify/lang-proto.js
  47. 0 {site → site-old}/js/google-code-prettify/lang-scala.js
  48. 0 {site → site-old}/js/google-code-prettify/lang-sql.js
  49. 0 {site → site-old}/js/google-code-prettify/lang-tex.js
  50. 0 {site → site-old}/js/google-code-prettify/lang-vb.js
  51. 0 {site → site-old}/js/google-code-prettify/lang-vhdl.js
  52. 0 {site → site-old}/js/google-code-prettify/lang-wiki.js
  53. 0 {site → site-old}/js/google-code-prettify/lang-xq.js
  54. 0 {site → site-old}/js/google-code-prettify/lang-yaml.js
  55. 0 {site → site-old}/js/google-code-prettify/prettify.css
  56. 0 {site → site-old}/js/google-code-prettify/prettify.js
  57. 0 {site → site-old}/tutorial.html
  58. +25 −0 site/app/controllers/application.js
  59. +211 −0 site/app/controllers/main.js
  60. +68 −0 site/app/views/layouts/application.html.jade
  61. +13 −0 site/app/views/main/changelog.html.jade
  62. +54 −0 site/app/views/main/community.html.jade
  63. +19 −0 site/app/views/main/documentation.html.jade
  64. +38 −0 site/app/views/main/faq.html.jade
  65. +3 −0 site/app/views/main/index.html.jade
  66. +11 −0 site/app/views/main/tutorial.html.jade
  67. +31 −0 site/config/development.js
  68. +9 −0 site/config/environment.js
  69. +15 −0 site/config/init.js
  70. +32 −0 site/config/production.js
  71. +29 −0 site/config/router.js
  72. +1 −0 site/node_modules/.bin/jade
  73. +1 −0 site/node_modules/.bin/marked
  74. +14 −0 site/node_modules/jade/.npmignore
  75. +22 −0 site/node_modules/jade/LICENSE
  76. +1,299 −0 site/node_modules/jade/Readme.md
  77. +168 −0 site/node_modules/jade/bin/jade
  78. +4 −0 site/node_modules/jade/index.js
  79. +3,586 −0 site/node_modules/jade/jade.js
  80. +510 −0 site/node_modules/jade/jade.md
  81. +2 −0 site/node_modules/jade/jade.min.js
  82. +654 −0 site/node_modules/jade/lib/compiler.js
  83. +18 −0 site/node_modules/jade/lib/doctypes.js
  84. +97 −0 site/node_modules/jade/lib/filters.js
  85. +28 −0 site/node_modules/jade/lib/inline-tags.js
  86. +253 −0 site/node_modules/jade/lib/jade.js
  87. +774 −0 site/node_modules/jade/lib/lexer.js
  88. +77 −0 site/node_modules/jade/lib/nodes/attrs.js
  89. +33 −0 site/node_modules/jade/lib/nodes/block-comment.js
  90. +122 −0 site/node_modules/jade/lib/nodes/block.js
  91. +43 −0 site/node_modules/jade/lib/nodes/case.js
  92. +35 −0 site/node_modules/jade/lib/nodes/code.js
  93. +32 −0 site/node_modules/jade/lib/nodes/comment.js
  94. +29 −0 site/node_modules/jade/lib/nodes/doctype.js
  95. +35 −0 site/node_modules/jade/lib/nodes/each.js
  96. +35 −0 site/node_modules/jade/lib/nodes/filter.js
  97. +20 −0 site/node_modules/jade/lib/nodes/index.js
  98. +32 −0 site/node_modules/jade/lib/nodes/literal.js
  99. +36 −0 site/node_modules/jade/lib/nodes/mixin.js
  100. +25 −0 site/node_modules/jade/lib/nodes/node.js
  101. +95 −0 site/node_modules/jade/lib/nodes/tag.js
  102. +36 −0 site/node_modules/jade/lib/nodes/text.js
  103. +715 −0 site/node_modules/jade/lib/parser.js
  104. +174 −0 site/node_modules/jade/lib/runtime.js
  105. +19 −0 site/node_modules/jade/lib/self-closing.js
  106. +64 −0 site/node_modules/jade/lib/utils.js
  107. +4 −0 site/node_modules/jade/node_modules/commander/.npmignore
  108. +4 −0 site/node_modules/jade/node_modules/commander/.travis.yml
  109. +107 −0 site/node_modules/jade/node_modules/commander/History.md
  110. +7 −0 site/node_modules/jade/node_modules/commander/Makefile
  111. +262 −0 site/node_modules/jade/node_modules/commander/Readme.md
  112. +2 −0 site/node_modules/jade/node_modules/commander/index.js
  113. +1,026 −0 site/node_modules/jade/node_modules/commander/lib/commander.js
  114. +34 −0 site/node_modules/jade/node_modules/commander/package.json
  115. +2 −0 site/node_modules/jade/node_modules/mkdirp/.npmignore
  116. +4 −0 site/node_modules/jade/node_modules/mkdirp/.travis.yml
  117. +21 −0 site/node_modules/jade/node_modules/mkdirp/LICENSE
  118. +61 −0 site/node_modules/jade/node_modules/mkdirp/README.markdown
  119. +6 −0 site/node_modules/jade/node_modules/mkdirp/examples/pow.js
  120. +82 −0 site/node_modules/jade/node_modules/mkdirp/index.js
  121. +32 −0 site/node_modules/jade/node_modules/mkdirp/package.json
  122. +38 −0 site/node_modules/jade/node_modules/mkdirp/test/chmod.js
  123. +37 −0 site/node_modules/jade/node_modules/mkdirp/test/clobber.js
  124. +28 −0 site/node_modules/jade/node_modules/mkdirp/test/mkdirp.js
  125. +32 −0 site/node_modules/jade/node_modules/mkdirp/test/perm.js
  126. +39 −0 site/node_modules/jade/node_modules/mkdirp/test/perm_sync.js
  127. +41 −0 site/node_modules/jade/node_modules/mkdirp/test/race.js
  128. +32 −0 site/node_modules/jade/node_modules/mkdirp/test/rel.js
  129. +25 −0 site/node_modules/jade/node_modules/mkdirp/test/return.js
  130. +24 −0 site/node_modules/jade/node_modules/mkdirp/test/return_sync.js
  131. +18 −0 site/node_modules/jade/node_modules/mkdirp/test/root.js
  132. +32 −0 site/node_modules/jade/node_modules/mkdirp/test/sync.js
  133. +28 −0 site/node_modules/jade/node_modules/mkdirp/test/umask.js
  134. +32 −0 site/node_modules/jade/node_modules/mkdirp/test/umask_sync.js
  135. +47 −0 site/node_modules/jade/package.json
  136. +179 −0 site/node_modules/jade/runtime.js
  137. +1 −0 site/node_modules/jade/runtime.min.js
  138. +7 −0 site/node_modules/jade/test.jade
  139. +5 −0 site/node_modules/jade/testing/head.jade
  140. +1 −0 site/node_modules/jade/testing/index.jade
  141. +14 −0 site/node_modules/jade/testing/index.js
  142. +10 −0 site/node_modules/jade/testing/layout.jade
  143. +7 −0 site/node_modules/jade/testing/user.jade
  144. +27 −0 site/node_modules/jade/testing/user.js
  145. +2 −0 site/node_modules/marked/.npmignore
  146. +19 −0 site/node_modules/marked/LICENSE
  147. +9 −0 site/node_modules/marked/Makefile
  148. +125 −0 site/node_modules/marked/README.md
  149. +127 −0 site/node_modules/marked/bin/marked
  150. +1 −0 site/node_modules/marked/index.js
  151. +791 −0 site/node_modules/marked/lib/marked.js
  152. +49 −0 site/node_modules/marked/man/marked.1
  153. +40 −0 site/node_modules/marked/package.json
  154. +5,774 −0 site/public/css/bootstrap.css
  155. +9 −0 site/public/css/bootstrap.min.css
  156. +1,058 −0 site/public/css/bootstrap.responsive.css
  157. +9 −0 site/public/css/bootstrap.responsive.min.css
  158. +507 −0 site/public/css/style.css
  159. BIN site/public/favicon.ico
  160. BIN site/public/img/changelog-dark-72.png
  161. BIN site/public/img/changelog-light-72.png
  162. BIN site/public/img/community-dark-72.png
  163. BIN site/public/img/community-light-72.png
  164. BIN site/public/img/docs-dark-72.png
  165. BIN site/public/img/docs-light-72.png
  166. BIN site/public/img/faq-dark-72.png
  167. BIN site/public/img/faq-light-72.png
  168. BIN site/public/img/glyphicons-halflings-white.png
  169. BIN site/public/img/glyphicons-halflings.png
  170. BIN site/public/img/home-dark-72.png
  171. BIN site/public/img/home-light-72.png
  172. BIN site/public/img/tuts-dark-72.png
  173. BIN site/public/img/tuts-light-72.png
  174. BIN site/public/img/whitey.png
  175. +2,027 −0 site/public/js/bootstrap.js
  176. +6 −0 site/public/js/bootstrap.min.js
  177. +2 −0 site/public/js/jquery.min.js
  178. +94 −0 site/public/js/site.js
  179. +84 −47 templates/Jakefile
  180. +6 −0 templates/base/Jakefile.ejs
  181. +1 −1 templates/base/public/js/jquery.min.js
  182. +3 −4 templates/resource/model.ejs
  183. +12 −0 templates/resource/test.ejs
  184. +3 −4 templates/scaffold/model.ejs
  185. +680 −0 tutorial.md
View
1 .gitignore
@@ -11,6 +11,7 @@ node_modules
tmtags
*.DS_Store
examples/*/log/*
+site/log/*
.log
npm-debug.log
doc/
View
45 bin/cli.js
@@ -21,6 +21,9 @@ var cwd = process.cwd()
, filepath
, die
, jake
+ , jakeArgs
+ , jakeProgram
+ , jakeLoader
, start;
// Usage dialog
@@ -126,9 +129,11 @@ if (cmds.length) {
cmd = '';
// Some commands take only one arg
- if (!(cmds[0] == 'secret' ||
+ if (!(cmds[0] == 'jake' ||
+ cmds[0] == 'secret' ||
cmds[0] == 'db:init' ||
- cmds[0] == 'console') && !cmds[1]) {
+ cmds[0] == 'console')
+ && !cmds[1]) {
throw new Error(cmds[0] + ' command requires another argument.');
}
@@ -148,6 +153,10 @@ if (cmds.length) {
// Add Jake argument based on commands
switch (cmds[0]) {
+ case 'jake':
+ cmd = 'jake';
+ jakeArgs = cmds.slice(1);
+ break;
case 'console':
// Create DBs
cmd += 'console:start[' + (cmds[1] || 'development') + ']';
@@ -189,13 +198,26 @@ if (cmds.length) {
}
jake = require('jake');
- jake.program.init({
- quiet: !opts.debug
- , trace: true
- });
- jake.loader.loadFile(filepath);
- jake.program.setTaskNames([cmd]);
- jake.program.run();
+ jakeProgram = jake.program;
+ jakeLoader = jake.loader;
+ // Load Geddy's bundled Jakefile
+ jakeLoader.loadFile(filepath);
+ if (cmd == 'jake') {
+ jakeProgram.parseArgs(jakeArgs);
+ // Load Jakefile and jakelibdir files for app
+ jakeLoader.loadFile(jakeProgram.opts.jakefile);
+ jakeLoader.loadDirectory(jakeProgram.opts.jakelibdir);
+ // Prepend env:init to load Geddy env
+ jakeProgram.taskNames.unshift('env:init');
+ }
+ else {
+ jakeProgram.init({
+ quiet: !opts.debug
+ , trace: true
+ });
+ jakeProgram.setTaskNames([cmd]);
+ }
+ jakeProgram.run();
}
// Just `geddy` -- start the server
else {
@@ -204,8 +226,7 @@ else {
if (err) {
die(usage);
}
- else {
- start();
- }
+
+ start();
});
}
View
12 changelog.md
@@ -0,0 +1,12 @@
+### 0.5.0
++ removed models from geddy core
++ removed utilities from geddy core
++ removed router from geddy core
++ added [model](https://github.com/mde/model) as a dependency
++ added [utilities](https://github.com/mde/utilities) as a dependency
++ added [barista](https://github.com/kieran/barista) as a dependency
++ added the `geddy console` command
++ added the `geddy exec` command
++ added a ton of tests
++ a ton of minor bug fixes
++ created a new website
View
7 deps/templato/lib/engines/ejs.js
@@ -1,8 +1,11 @@
-var TemplatoEJS = (function() {
+var path = require('path')
+ , TemplatoEJS;
+
+TemplatoEJS = (function() {
function TemplatoEJS() {
try {
- this.engine = this.engine || require('ejs');
+ this.engine = this.engine || require(path.join(process.cwd(), 'node_modules', 'ejs'));
} catch(err) {
throw "To use EJS you will need to install it: [sudo] npm install [-g] ejs";
}
View
7 deps/templato/lib/engines/handlebars.js
@@ -1,8 +1,11 @@
-var TemplatoHandlebars = (function() {
+var path = require('path')
+ , TemplatoHandlebars;
+
+TemplatoHandlebars = (function() {
function TemplatoHandlebars() {
try {
- this.engine = this.engine || require('handlebars');
+ this.engine = this.engine || require(path.join(process.cwd(), 'node_modules', 'handlebars'));
} catch(err) {
throw "To use Handlebars you will need to install it: [sudo] npm install [-g] handlebars";
}
View
7 deps/templato/lib/engines/jade.js
@@ -1,8 +1,11 @@
-var TemplatoJade = (function() {
+var path = require('path')
+ , TemplatoJade;
+
+TemplatoJade = (function() {
function TemplatoJade() {
try {
- this.engine = this.engine || require('jade');
+ this.engine = this.engine || require(path.join(process.cwd(), 'node_modules', 'jade'));
} catch(err) {
throw "To use Jade you will need to install it: [sudo] npm install [-g] jade";
}
View
6 deps/templato/lib/engines/mustache.js
@@ -1,10 +1,12 @@
require('../../color');
+var path = require('path')
+ , TemplatoMustache;
-var TemplatoMustache = (function() {
+TemplatoMustache = (function() {
function TemplatoMustache() {
try {
- this.engine = this.engine || require('handlebars');
+ this.engine = this.engine || require(path.join(process.cwd(), 'node_modules', 'mustache'));
} catch(err) {
throw [
"To use Handlebars you will need to install it: [sudo] npm install [-g] handlebars"
View
72 docs/1-architecture.md
@@ -0,0 +1,72 @@
+Geddy is built on the same MVC principles that many popular frameworks are based on. Every Geddy app has it's models, controllers, and views as well as config files and routes.
+
+* * *
+
+#### structure
+
+```
+├── app
+│   ├── controllers
+│   │   ├── application.js
+│   │   └── main.js
+│   ├── helpers
+│   ├── models
+│   └── views
+│   ├── layouts
+│   │   └── application.html.jade
+│   └── main
+│   └── index.html.jade
+├── config
+ ├── development.js
+ ├── environment.js
+ ├── init.js
+ ├── production.js
+ └── router.js
+├── lib
+├── log
+├── node_modules
+└── public
+```
+
+* * *
+
+#### config
+`geddy.config`
+
+Geddy has built in configuration management. Global config options should go in your ‘config/environments.js` file. Likewise, your production and development config options should go in their respective files
+
+If you want to start up your app in a specific environment, use the `-e` option:
+
+```
+$ geddy -e production
+```
+
+* * *
+
+#### logger
+`geddy.log[level]`
+
+Geddy automatically logs requests to an access log, and you can log anything you'd like to stdout or a file. It supports 9 different log levels from debug to emergency.
+
+##### levels
+- `access`: outputs to the access log and stdout
+- `debug`: debug level logging
+- `info`: info level logging
+- `notice`: notice level logging
+- `warning`: warning level logging
+- `error`: error level logging, prints to stdout and stderr
+- `critical`: critical level logging
+- `alert`: alert level logging
+- `emergency`: emergency level logging
+
+##### examples
+```
+geddy.log.debug(‘someting to debug`)
+// prints `something to debug` to the console
+
+
+geddy.log.error(‘something went wrong’)
+// prints ‘something went wrong’ to stderr and the console
+```
+
+* * *
View
110 docs/2-router.md
@@ -0,0 +1,110 @@
+Geddy uses [Barista](http://github.com/kieran/barista) as it's router. Its API is very similar to rails routes. Both general purpose resource based routes and individually defined routes are possible.
+
+* * *
+
+#### .match
+`router.match( path [, method] )`
+
+defines the url to match to a controller action.
+
+##### path
+- `path [string]`: the url to match to an action
+
+##### method
+- `method [string]`: the http method to match
+
+##### examples
+```
+router.match(‘/‘).to(‘Main.index’);
+// will route any request to ‘/‘ to the Main controller’s index action
+
+
+router.match( '/products/:id', 'GET' ).to( 'products.show' )
+// will route ‘/products/5’ to Products.show()
+// and set the id paramer to be 5
+
+
+router.match( '/profiles/:username', 'GET' ).to( 'users.show' )
+// will route ‘/products/dan’ to Users.show()
+// and set the username paramer to be dan
+
+
+router.match( '/products/:id(.:format)', 'GET' ).to( 'products.show' )
+// things enclosed in parentheses are optional
+```
+
+* * *
+
+#### .to
+`router.match( path ).to( action )`
+
+defines the action to map the path to.
+
+##### action
+- `action [string]`: a controller name plus an action name as a string
+- `action [object]`: an object that defines a controller and action property
+
+##### examples
+```
+router.match(‘/‘).to(‘Main.index’);
+// will route any request to ‘/‘ to the Main controller’s index action
+
+
+router.match(‘/‘).to({controller: ‘Main’, action: ‘index’});
+// will route any request to ‘/‘ to the Main controller’s index action
+```
+
+* * *
+
+#### .get
+`router.get( path )`
+
+Equivalent to `router.match( path, 'GET' )`
+
+* * *
+
+#### .post
+`router.post( path )`
+
+Equivalent to `router.match( path, ‘POST’ )`
+
+* * *
+
+#### .put
+`router.put( path )`
+
+Equivalent to `router.match( path, ‘PUT’ )`
+
+* * *
+
+#### .del
+`router.del( path )`
+
+Equivalent to `router.match( path, ‘DELETE’ )`
+
+* * *
+
+#### .resource
+`router.resource( controller )`
+
+generates standard resource routes for a controller name
+
+##### controller
+- `controller [string]`: the camelCased controller name that needs resourceful routes
+
+##### examples
+```
+router.resource( 'products' )
+
+// is equivalent to:
+
+router.get( '/products(.:format)' ).to( 'products.index' )
+router.get( '/products/add(.:format)' ).to( 'products.add' )
+router.get( '/products/:id(.:format)' ).to('products.show' )
+router.get('/products/:id/edit(.:format)' ).to( 'products.edit' )
+router.post('/products(.:format)' ).to( 'products.create' )
+router.put('/products/:id(.:format)' ).to( 'products.update' )
+router.del('/products/:id(.:format)' ).to( 'products.destroy' )
+```
+
+* * *
View
208 docs/3-controllers.md
@@ -0,0 +1,208 @@
+Controllers define the different actions that your users can interact with.
+
+* * *
+
+#### .request
+`this.request`
+
+The raw `http.ServerRequest` object for this request/response cycle.
+
+* * *
+
+#### .respnose
+`this.response`
+
+The raw `http.ServerResponse` object for this request/response cycle.
+
+* * *
+
+#### .params
+`this.params`
+
+The parsed params for the request. `params` is also passed as an argument to the action, it was added as an instance field for convenience.
+
+* * *
+
+#### .cookies
+`this.cookies`
+
+Cookies collection from the request
+
+* * *
+
+#### .name
+`this.name`
+
+The name of the controller constructor function, in CamelCase with uppercase initial letter.
+
+* * *
+
+#### .respondsWith
+`this.respondsWith`
+
+Content-type the controller can respond with.
+
+##### example
+```
+this.respondsWith = [‘txt’,’json’,’html’];
+```
+
+* * *
+
+#### .before
+`before(filter, [options])`
+
+Adds an action to be performed before a response is rendered.
+
+##### filter
+- `filter [function]` Action to add to the afterFilter list.
+
+##### options
+- `except [array]` List of actions where the before-filter should not be performed.
+- `only [array]` List of actions where the before-filter should only be performed.
+
+##### examples
+```
+this.before(someFunction);
+// runs someFunction before the response is rendered
+
+
+this.before(someFunction, {except: [‘index’, ‘home’]});
+// won’t run someFunction if this is the index or home action
+
+
+this.before(someFunction, {only: [‘add’, ‘update’, ‘remove’]}
+// will only run someFunction if this is the add, update, or remove action
+```
+
+* * *
+
+#### .after
+`after(filter, [options])`
+
+Adds an action to be performed after a response is rendered.
+
+##### filter
+- `filter [function]` Action to be performed
+
+##### options
+- `except [array]` List of actions where the after-filter should not be performed.
+- `only [array]` List of actions where the after-filter should only be performed.
+
+##### examples
+```
+this.after(someFunction);
+// runs someFunction after the response is rendered
+
+
+this.after(someFunction, {except: [‘index’, ‘home’]});
+// won’t run someFunction if this is the index or home action
+
+
+this.after(someFunction, {only: [‘add’, ‘update’, ‘remove’]}
+// will only run someFunction if this is the add, update, or remove action
+```
+
+* * *
+
+#### .protectFromForgery
+`protectFromForgery()`
+
+Prevents cross site requests from completing.
+
+* * *
+
+#### .redirect
+`redirect(to)`
+
+##### to [string]
+- if `to` is a string, it will redirect to the url in that string
+
+##### to [object]
+- `controller [string]`: a controller name
+- `action [string]`: an action name
+- `format [string]`: the file extension
+
+Sends a 302 redirect to the client, based on either a simple string-URL, or a controller/action/format combination.
+
+##### examples
+```
+this.redirect(‘/users/1’);
+// will redirect the browser to /users/1
+
+
+this.redirect({controller: ‘users’, action: ‘show’, id: 1});
+// will redirect the browser to /users/1
+```
+
+* * *
+
+#### .error
+`error(err)`
+
+Respond to a request with an appropriate HTTP error-code. If a status-code is set on the error object, uses that as the error's status-code. Otherwise, responds with a 500 for the status-code.
+
+##### err
+- `statusCode [number]` the code to send to the client
+- `msg [string]` the message to send to the client
+
+##### examples
+```
+this.error()
+// sends a 500
+
+
+this.error({statusCode: 501})
+// sends a 501
+```
+
+* * *
+
+#### .transfer
+```
+transfer(action)
+```
+
+Transfer a request from its original action to a new one. The entire request cycle is repeated, including before-filters.
+
+##### action
+- `action [string]`: name of the new action designated to handle the request.
+- `action [object]`: The new action designated to handle the request.
+
+* * *
+
+#### .respond
+```
+respond(data, options)
+```
+
+Performs content-negotiation, and renders a response.
+
+##### data
+- `data [object]`: an object with properties to send to the view
+
+##### options
+- `layout [string]`: the path to the layout file to use
+- `layout [false]`: a flag to not use a layout file
+- `format [string]`: the format to render
+- `template [string]`: The path (without file extensions) to the template to use to render this response
+
+##### examples
+```
+this.respond(params);
+// send the params object to the view, then send the response
+
+
+this.respond({posts: posts});
+// send the passed in object to the view, then send the response
+
+
+this.respond(params, {template: ‘path/to/template’});
+// send params to path/to/template, render it, then send the response
+
+
+this.respond(params, {format: ‘json’});
+// send the params object as the response in json format
+```
+
+* * *
View
422 docs/4-models.md
@@ -0,0 +1,422 @@
+Geddy uses the [Model](http://github.com/mde/model) module for it's model layer. It's an abstract ORM that is compatible with many different types of databases, from Postgres to in memory, and MongoDB ro Riak.
+
+* * *
+
+#### definition
+Model uses a pretty simple syntax for defining a model. (It should look familiar to anyone who has used an ORM like ActiveRecord, DataMapper, Django's models, or SQLAlchemy.)
+
+* * *
+
+#### .defineProperties
+`defineProperties( properties )`
+
+defines the properties for your model.
+
+##### properties
+- `properties [object]`: an object keyed by name of properties to define
+
+##### example
+```
+var User = function () {
+ this.defineProperties({
+ login: {type: 'string', required: true}
+ , password: {type: 'string', required: true}
+ , lastName: {type: 'string'}
+ , firstName: {type: 'string'}
+ });
+}
+```
+
+* * *
+
+#### .property
+`property( name, type, options )`
+
+defines a single property
+
+##### name
+- `name [string]`: the name of the property
+
+##### type
+- `type [string]`: the type of the property
+ - `’string’`
+ - `’text’`
+ - `’number’`
+ - `’int’`
+ - `’boolean’`
+ - `’object’`
+ - `’array’`
+ - `’datetime’`
+ - `’date’`
+ - `’time’`
+
+##### options
+- `required [boolean]`: sets the property to be required
+
+##### examples
+```
+this.property('login', 'string', {required: true});
+this.property('password', 'string', {required: true});
+this.property(‘joined’, ‘datetime);
+this.property(‘premium’, ’boolean);
+```
+
+* * *
+
+#### .validatesPresent
+`validatesPresent( property )`
+
+Sets up a validation to make sure that the property is present.
+
+##### property
+- `property [string]`: the name of the property to validate
+
+##### example
+```
+this.validatesPresent('login');
+// makes sure that the login property is present
+```
+
+* * *
+
+#### .validatesFormat
+`validatesFormat( property, regex, options )`
+
+Sets up a validation to make sure that the property is formatted correctly.
+
+##### property
+- `property [string]`: the name of the property to validate
+
+##### regex
+- `regex [regex]`: a regular expression that the property value must pass
+
+##### options
+- `message [string]`: a message to give the use if the validation fails
+
+##### example
+```
+this.validatesFormat('login', /[a-z]+/, {message: ‘cannot contain numbers’});
+// makes sure that the login property does not contain numbers
+```
+
+* * *
+
+#### .validatesLength
+`validatesLength( property, options )`
+
+Sets up a validation to make sure that the property meets certain lenght requirements.
+
+##### property
+- `property [string]`: the name of the property to validate
+
+##### options
+- `min [number]`: the minimum length of the property
+- `max [number]`: the maximum length of the property
+
+##### example
+```
+this.validatesLength(‘login', {min: ‘3’});
+// makes sure that the login property is at least 3 characters long
+
+
+this.validatesLength(‘login', {min: ‘20’});
+// makes sure that the login property is not longer than 20 characters
+```
+
+* * *
+
+#### .validatesConfirmed
+`validatesConfirmed( property, param )`
+
+Sets up a validation to make sure that the property has been confirmed.
+
+##### property
+- `property [string]`: the name of the property to validate
+
+##### param
+- `param [string]`: the param required to match
+
+##### example
+```
+this.validatesConfirmed('password', 'confirmPassword');
+// confirms that password and confirmPassword are equal
+```
+
+* * *
+
+#### .validatesWithFunction
+`validatesWithFunction( property, fn )`
+
+Sets up a validation to make sure that the property has been confirmed.
+
+##### property
+- `property [string]`: the name of the property to validate
+
+##### fn
+- `fn [function]`: a function which, when passed the value of the property, will return true or false
+
+##### example
+```
+this.validatesWithFunction('password', function (val) {
+ // Something that returns true or false
+ return val.length > 0;
+});
+// uses the function to see if th length of password is greater than 0
+```
+
+* * *
+
+#### .hasOne
+`hasOne( model )`
+
+Sets up a has one relationship between this model and another.
+
+##### model
+- `model [string]`: the name of the model that this model has one of.
+
+##### example
+```
+this.hasOne('Profile');
+// sets up a has one relationship
+// user -> has one -> profile
+```
+
+* * *
+
+#### .hasMany
+`hasMany( model )`
+
+Sets up a has many relationship between this model and another.
+
+##### model
+- `model [string]`: the pluralized name of the model that this model has many of.
+
+##### example
+```
+this.hasMany(‘Friends’);
+// sets up a has many relationship
+// user -> has many -> friends
+```
+
+* * *
+
+#### .adapter
+`this.adapter`
+
+Defines the database adapter for this model
+
+##### examples
+```
+this.adapter = ‘mongo’;
+// makes this model use mongo for it’s database
+
+
+this.adapter = ‘riak’
+
+
+this.adapter = ‘postgres’
+
+
+this.adapter = ‘memory’
+```
+
+* * *
+
+#### instance
+
+Instance methods can be defined in the model definition as well.
+
+##### example
+```
+var User = function () {
+...
+ this.someMethod = function () {
+ // Do some stuff
+ };
+ // sets up a someMethod method on each instance of this model
+...
+};
+```
+
+* * *
+
+#### .isValid
+`isValid()`
+
+Returns true if the model instance passes all validations, otherwise it returns false.
+
+##### example
+```
+user.isValid()
+```
+
+* * *
+
+#### .save
+`save( fn )`
+
+Saves the instance to the database.
+
+##### fn
+- `fn [function]`: the function to be called when saving is complete
+
+##### example
+```
+user.save(function (err, data) {
+// do things
+});
+// saves the user then calls the callback function
+```
+
+* * *
+
+#### .updateProperties
+`updateProperties( properties )`
+
+Updates the properties of a model and asserts that they are valid; This method will not call save on the instance.
+
+##### properties
+- `properties [object]`: an object who’s keys are property names and its values are the values to change the property to.
+
+##### example
+```
+user.updateProperties({
+ login: 'alerxst'
+});
+// updates the login property and validates it
+```
+
+* * *
+
+#### static
+
+docs coming soon
+
+* * *
+
+#### .create
+`create( params )`
+
+Creates a new model instance and returns it.
+
+##### params
+- `params [object]`: an object whos keys are model properties
+
+##### example
+```
+var params = {
+ login: 'alex'
+, password: 'lerxst'
+, lastName: 'Lifeson'
+, firstName: 'Alex'
+};
+var user = User.create(params);
+```
+
+* * *
+
+#### .first
+`first( query, options, fn )`
+
+Use the `first` method to find a single item. You can pass it an id, or a set of query parameters in the form of an object-literal. In the case of a query, it will return the first item that matches, according to whatever sort you've specified.
+
+##### query [string]
+- `query [string]`: if the query is a string, it will be assumed that it’s an id
+
+##### query [object]
+- `query [object]`: if the query is an object, it will be interpreted as a Query object
+
+##### example
+```
+User.first(‘sdfs-asd-1’, function (err, user) {
+ // do stuff with user
+});
+
+
+User.first({login: 'alerxst'}, function (err, user) {
+ // do stuff with user
+});
+```
+
+* * *
+
+#### .all
+`all( query, options, fn )`
+
+Use the `all` method to find lots of items. Pass it a set of query parameters in the form of an object-literal, where each key is a field to compare, and the value is either a simple value for comparison (equal to), or another object-literal where the key is the comparison-operator, and the value is the value to use for the comparison.
+
+##### query [object]
+- `query [object]`: if the query is an object, it will be interpreted as a Query object
+
+##### options
+- `sort [object]`: each key is a property name, each value can either be `asc` or `desc`
+
+##### example
+```
+User.all({location: ‘san francisco’}, function (err, users) {
+ // do stuff with users
+});
+
+
+User.all({location: ‘san francisco’}, {sort: {createdAt: ‘desc’}}, function (err, users) {
+ // do stuff with users
+});
+```
+
+* * *
+
+#### .remove
+`remove( id, fn )`
+
+Remove an instance from the database by id.
+
+##### id
+- `id [string]`: the id of the instance to be removed
+
+##### examples
+```
+User.remove(‘abc-123’, function (err, data) {
+ // do something now that it’s removed.
+});
+```
+
+* * *
+
+#### queries
+
+docs coming soon
+
+* * *
+
+#### events
+
+Both the base model 'constructors,' and model instances are EventEmitters. The
+emit events during the create/update/remove lifecycle of model instances. In all
+cases, the plain-named event is fired after the event in question, the
+'before'-prefixed event, of course happens before.
+
+The 'constructor' for a model emits the following events:
+
+ - beforeCreate
+ - create
+ - beforeValidate
+ - validate
+ - beforeUpdateProperties
+ - updateProperties
+ - beforeSave (new instances, single and bulk)
+ - save (new instances, single and bulk)
+ - beforeUpdate (existing single instances, bulk updates)
+ - update (existing single instances, bulk updates)
+ - beforeRemove
+ - remove
+
+Model-item instances emit these events:
+
+ - beforeUpdateProperties
+ - updateProperties
+ - beforeSave
+ - save
+ - beforeUpdate
+ - update
+
+* * *
View
317 docs/5-templates.md
@@ -0,0 +1,317 @@
+Geddy's view layer provides a versitile set of templating languages and helpers to get you started quickly.
+
+* * *
+
+#### engines
+The view layer supports these four templating engines:
+
++ EJS
++ Jade
++ Mustache
++ Handlebars
+
+To use them, just give your template the correct file extension.
+
+* * *
+
+#### yield
+Yield is a function that's only available on layout templates. Yield, yields the template content and is put in place where the yield function is called.
+
+* * *
+
+#### partial
+`partial(partialURL<String>, data<Object>)`
+
+Partial takes a partialURL which is the location to a partial template and a data object which is the data to render the partial with(params, etc), then it renders the partial and puts the contents in place where the partial function was called.
+
+* * *
+
+#### truncate
+`truncate(string<String>, options<Integer/Object>)`
+
+Truncates a given `string` after a specified `length` if `string` is longer than `length`. The last character will be replace with an `omission` for a total length not exceeding `length`.
+
+#####Options [Integer]:
+- If an `options` is an integer it will be assumed that is the desired `length`
+
+#####Options [Object]:
+- `length [Integer]` Length the output string will be(Default: 30)
+- `len [Integer]` Alias for `length`
+- `omission [String]` Replace the last letters with an omission(Default: '...')
+- `ellipsis [String]` Alias for `omission`
+- `seperator [String/RegExp]` Break the truncated text at the nearest `seperator`
+
+#####Warnings:
+- Please be aware that truncating HTML elements may result in malformed HTML returned. If you'd like safe HTML truncation look at `truncateHTML`
+
+#####Examples:
+```
+truncate('Once upon a time in a world', { length: 10 })
+// => 'Once up...'
+
+
+truncate('Once upon a time in a world', { length: 20, omission: '...(continued)' })
+// => 'Once u...(continued)'
+
+
+truncate('Once upon a time in a world', { length: 15, seperator: /\s/ })
+// => 'Once upon a...'
+// Normal Output: => 'Once upon a ...'
+
+
+truncate('Once upon a time in a world', { length: 15, seperator: ' ' })
+// => 'Once upon a...'
+// Normal Output: => 'Once upon a ...'
+
+
+truncate('<p>Once upon a time</p>', { length: 20 })
+// => '<p>Once upon a ti...'
+```
+
+* * *
+
+#### truncateHTML
+`truncateHTML(string<String>, options<Integer/Object>)`
+
+Truncates a given `string` after a specified `length` if `string` is longer than `length`. The lat character will be replace with an `omission` for a total length not exceeding `length`. If `once` is true, only the first string in the first HTML element will be truncated leaving others as they were.
+
+#####Options [Object]:
+- `once`[Boolean] If true only the first string in the first HTML element will be truncated(Default: false)
+
+#####Notes:
+- All options available to `truncate` are available for `truncateHTML`
+- HTML elements are not included with the length of the truncation
+- HTML elements will not be truncated, so return value will always be safe for rendering
+
+#####Examples:
+```
+truncateHTML('<p>Once upon a time in a world</p>', { length: 10 })
+// => '<p>Once up...</p>'
+
+
+truncateHTML('<p>Once upon a time <small>in a world</small></p>', { length: 10 })
+// => '<p>Once up...<small>in a wo...</small></p>'
+
+
+truncateHTML('<p>Once upon a time <small>in a world</small></p>', { length: 10, once: true })
+// => '<p>Once up...<small>in a world</small></p>'
+```
+
+* * *
+
+#### imageLink
+`imageLink(source<String>, link<String/Object>, imageOptions<Object>, linkOptions<Object>)`
+
+Returns an anchor element to a given `link` with the given `linkOptions`, with the content being a image element to the given `source` and includes it's `imageOptions`
+
+#####Notes:
+- `linkto` is used on the backend so any `linkOption` will be used for `linkTo`
+- `imageTag` is used on the backend as well so any `imageOptions` will be used for `imageTag`
+
+#####Examples:
+```
+imageLink('images/google.png', 'http://google.com')
+// => '<a href="http://google.com"><img alt="images/google.png" src="images/google.png" /></a>'
+
+
+imageLink('images/google.png', 'http://google.com', { alt: '' }
+// => '<a href="http://google.com"><img alt="" src="images/google.png" /></a>'
+
+
+imageLink('images/google.png', 'http://google.com', { alt: '', size: '40x50' })
+// => '<a href="http://google.com"><img alt="" height="50" src="images/google.png" width="40" /></a>'
+```
+
+* * *
+
+#### imageTag
+`imageTag(source<String>, htmlOptions<Object>)`
+
+Returns an image tag with the src to a `source` and includes all the given `htmlOptions`
+
+#####Custom HTML options:
+- `size`[String] Takes a string including the width and height "{width}x{height}"(e,g: '40x50') or it can take a single string included an integer "{size}"(e,g: '40') The first being results in "height='50' width='40'" the second results in the height and width being the same value. _Note_: If the format doesn't comply, it will be ignored
+
+#####Examples:
+```
+imageTag('images/google.png')
+// => '<img alt="images/google.png" src="images/google.png" />'
+
+
+imageTag('images/google.png', { alt: '' })
+// => '<img alt="" src="images/google.png" />'
+
+
+imageTag('images/google.png', { alt: '', size: '40x50' })
+// => '<img alt="" height="50" src="images/google.png" width="40" />'
+
+
+imageTag('images/google.png', { alt: '', size: 'a string' })
+// => '<img alt="" src="images/google.png" />'
+```
+
+* * *
+
+#### styleLink
+`styleLink(source<String>, htmlOptions<Object>)`
+
+Generates a style element pointing to `source` and includes all the given `htmlOptions`
+
+#####Examples:
+```
+styleLink('/css/styles.css')
+// => '<link href="/css/style.css" />'
+
+
+styleLink('/css/styles.css', { type: 'text/javascript' })
+// => '<link href="/css/style.css" rel="stylesheet" />'
+```
+
+* * *
+
+#### scriptLink
+`scriptLink(source<String>, htmlOptions<Object>)`
+
+Generates a script element pointing to `source` and includes all the given `htmlOptions`
+
+#####Examples:
+```
+scriptLink('/js/script.js')
+// => '<script src="/js/script.js"></script>'
+
+
+scriptLink('/js/script.js', { type: 'text/javascript' })
+// => '<script src="/js/script.js" type="text/javascript"></script>'
+```
+
+* * *
+
+#### linkTo
+`linkTo(content<String>, options<String/Object>, htmlOptions<Object>)`
+
+Generates a link from the given `options`, then returns a anchor tag with the `content` and the `htmlOptions` provided
+
+#####Examples:
+```
+linkTo('some content', 'http://google.com')
+// => '<a href="http://google.com">some content</a>'
+
+
+linkTo('some content', 'http://google.com', { data: {goTo: 'http://google.com'} })
+// => '<a data-go-to="http://google.com" href="http://google.com">some content</a>'
+```
+
+* * *
+
+#### urlFor
+`urlFor(options<String/Object>)`
+
+Returns a URL based on the `options` provided
+
+#####Options [String]:
+- `'back'` [String] The 'back' string will return a URL that points to the last URL in history
+
+#####Options [Object]:
+- `relPath` [Boolean] If true, the relative URL is returned(Default: false)
+- `protocol` [String] The protocol to use(Default: What your Geddy instance is using('http' default))
+- `username` [String] Includes a username in the path. Requires `password` or it'll be ignored
+- `password` [String] Includes a username in the path. Requires `password` or it'll be ignored
+- `subdomain` [String] Specifies the subdomain to prepend to `domain`
+- `domain` [String] Specifies the domain to point to. Required if `relPath` is false
+- `host` [String] Alias for `host`
+- `port` [Integer] Specify the port to connect to
+- `controller` [String] Specifies the controller to use for the path
+- `action` [String] Specifies the action to use for the path
+- `id` [String] Specifies an ID to use for displaying specific items
+- `trailingSlash` [Boolean] If true, adds a trailing slash to the end of the path/domain
+- `fragment` [String] Appends a fragment to the end of the path/domain
+- `anchor` [String] Alias for `fragment`
+
+#####Notes:
+- If `options` is a String it will just be returned, unless the String is equal to 'back'
+- Any other `options` added will be considered as a query to be appended to the URL
+
+#####Examples:
+```
+urlFor('http://google.com')
+// => 'http://google.com'
+
+
+urlFor({ controller: 'tasks', action: 'new', host: 'somehost.com' })
+// => 'http://somehost.com/tasks/new'
+
+
+urlFor({ controller: 'tasks', action: 'new', relPath: true })
+// => '/tasks/new'
+
+
+urlFor({ controller: 'tasks', action: 'new', relPath: true, trailingSlash: true })
+// => '/tasks/new/'
+
+
+urlFor({ host: 'somehost.com', protocol: 'https', username: 'username', password: 'password' })
+// => 'https://username:password@somehost.com'
+
+
+urlFor({ controller: 'tasks', action: 'new', host: 'somehost.com', protocol: 'https' })
+// => 'https://somehost.com/tasks/new'
+
+
+urlFor({ controller: 'tasks', action: 'edit', id: 'IwTEf55ivH', host: 'somehost.com' })
+// => 'http://somehost.com/tasks/IwTEf55ivH/edit'
+
+
+urlFor({ controller: 'tasks', action: 'new', host: 'somehost.com', anchor: 'submit' })
+// => 'http://somehost.com/tasks/new#submit'
+
+
+urlFor({ controller: 'tasks', action: 'new', host: 'somehost.com', authToken: 'some_token' })
+// => 'http://somehost.com/tasks/new?authToken=some_token'
+```
+
+* * *
+
+#### contentTag
+`contentTag(tag<String>, content<String>, htmlOptions<Object>)`
+
+Returns an HTML element from a given `tag` and includes the `content` and all `htmlOptions`
+
+#####Custom HTML options:
+- `data`[Array] The data attribute takes an Array containing data attributes you want, when parsed they each get parsed as a full data attribute(e,g: `data: { goTo: 'google.com' }` will be `data-go-to="google.com"`).
+
+#####Examples:
+```
+contentTag('p', 'this is some content')
+// => '<p>this is some content</p>'
+
+
+contentTag('input', 'sample value')
+// => '<input value="sample value" />'
+
+
+contentTag('input', 'sample value', { value: 'override sample value' })
+// => '<input autofocus="autofocus" type="text" value="sample value" />'
+
+
+contentTag('input', 'sample value', { type: 'text', autofocus: true })
+// => '<input autofocus="autofocus" type="text" value="sample value" />'
+
+
+contentTag('a', 'http://google.com')
+// => '<a href="http://google.com">http://google.com</a>'
+
+
+contentTag('a', 'hey there', { href: 'http://google.com' })
+// => '<a href="http://google.com">hey there</a>'
+
+
+contentTag('a', 'hey there', { href: 'http://google.com', data: { goTo: 'http://google.com' } })
+// => '<a data-go-to="http://google.com" href="http://google.com">hey there</a>'
+
+
+contentTag('a', 'hey there', { href: 'http://google.com', data_go_to: 'http://google.com' })
+// => '<a data-go-to="http://google.com" href="http://google.com">hey there</a>'
+```
+
+* * *
+
View
83 docs/6-CLI.md
@@ -0,0 +1,83 @@
+Geddy has a robust CLI tool to help you generate apps, run your tests, or play with your app in a console.
+
+####Options:
+
+- `—environment, -e`: Environment to use
+- `—port, -p`: Port to connect server to
+- `—workers, -w`: Number of workers to use (default: 1)
+- `—debug, -d`: Sets the log level to output debug messages to console
+- `—jade, -j`: When generating views, use Jade templates(Default: EJS)
+- `—handle, -H`: When generating views, use Handlebars templates(Default: EJS)
+- `—mustache, -m`: When generating views, use Mustache templates(Default: EJS)
+- `—version, -v`: Output the version of Geddy installed
+- `—help, -h`: Output the list of commands and options
+
+#### geddy
+`geddy` takes no arguments, it will run the geddy app in the current directory.
+
+```
+$ cd path/to/app
+$ geddy
+// will run the app in path/to/app
+```
+
+#### app
+`app` takes a single argument being the name you'd like, then it will generate a base application. If no name is given the command will fail. If you include the `—jade`, `—handle`, or `—mustache` option you can substitute the templating language to your liking
+
+```
+$ geddy app app_name
+// creates a geddy app using EJS
+```
+
+#### resource
+`resource` takes one or more arguments, the first being a name and the others being a set of model properties. This will create a controller, a model including the given model properties and a resource route.
+
+```
+$ geddy resource user name description password
+// This will create a user model, users controller, and user routes
+```
+
+#### scaffold
+`scaffold` takes one or more arguments, the first being a name and the others being a set of model properties. Scaffolding includes a controller, a model including the given model properties as well as a default model adapter a resource route and will create all views. If you also include the options `—jade`, `—handle` or `—mustache` you can substitute the template language to your liking.
+
+```
+$geddy scaffold user name description password
+// This will create a user model, users controller, user views, and user routes
+```
+
+#### controller
+`controller` takes a single argument being a name. It will create a new controller, a route and an index view. If you also include the options `—jade`, `—handle` or `—mustache` you can substitute the template language to your liking.
+
+```
+$ geddy controller users
+```
+
+#### model
+`model` takes one or more arguments, the first being a name and the others being a set of model properties. This will create a new model including the model properties given.
+
+```
+$ geddy model user name description password
+// creates a user model with name, description and password properties
+```
+
+#### secret
+`secret` doesn't take any arguments, it will find your config/environment file and create a new secret in it deleting any other secret.
+
+```
+$ geddy secret
+```
+
+#### console
+`console` doesn't take any arguments, it will start a geddy console.
+
+```
+$ geddy console
+```
+
+#### jake
+`jake` takes a task name, it will run a jake command in your apps context from your jakefile
+
+```
+$ geddy jake test
+// will run the test task in your jake file after loading up your app environment
+```
View
6 examples/todo_app/app/controllers/todos.js
@@ -47,8 +47,8 @@ var Todos = function () {
this.update = function (req, resp, params) {
var self = this;
geddy.model.Todo.first(params.id, function (err, todo) {
- todo.status = params.status;
- todo.title = params.title;
+ todo.updateAttributes(params);
+
todo.save(function (err, data) {
if (err) {
params.errors = err;
@@ -63,7 +63,7 @@ var Todos = function () {
this.remove = function (req, resp, params) {
var self = this;
- geddy.model.adapter.Todo.remove(params.id, function(err){
+ geddy.model.Todo.remove(params.id, function(err){
if (err) {
params.errors = err;
self.transfer('edit');
View
6 examples/todo_app/config/init.js
@@ -4,8 +4,4 @@ if (geddy.config.environment != 'development') {
process.addListener('uncaughtException', function (err) {
geddy.log.error(JSON.stringify(err));
});
-}
-geddy.todos = [];
-geddy.model.adapter = {};
-geddy.model.adapter.Todo = require(process.cwd() + '/lib/model_adapters/todo').Todo;
-
+}
View
60 examples/todo_app/lib/model_adapters/todo.js
@@ -1,60 +0,0 @@
-var Todo = new (function () {
-
- this.all = function (callback) {
- callback(null, geddy.todos);
- }
-
- this.load = function (id, callback) {
-
- for (var i in geddy.todos) {
- if (geddy.todos[i].id == id) {
- return callback(null, geddy.todos[i]);
- }
- }
- callback({message: "To Do not found"}, null);
-
- };
-
- this.save = function (todo, opts, callback) {
-
- if (typeof callback != 'function') {
- callback = function(){};
- }
-
- var todoErrors = null;
- for (var i in geddy.todos) {
-
- // if it's already there, save it
- if (geddy.todos[i].id == todo.id) {
- geddy.todos[i] = todo;
- todoErrors = geddy.model.Todo.create(todo).errors;
- return callback(todoErrors, todo);
- }
-
- }
- todo.saved = true;
- geddy.todos.push(todo);
- return callback(null, todo);
-
- }
-
- this.remove = function(id, callback) {
-
- if (typeof callback != 'function') {
- callback = function(){};
- }
-
- for (var i in geddy.todos) {
- if (geddy.todos[i].id == id) {
- geddy.todos.splice(i, 1);
- return callback(null);
- }
- }
-
- return callback({message: "To Do not found"});
-
- }
-
-})();
-
-exports.Todo = Todo;
View
20 examples/todo_app_coffee/app/controllers/todos.coffee
@@ -3,13 +3,7 @@ class Todos
index: (req, resp, params) ->
self = this
- geddy.model.adapter.Todo.all
- status:
- 'in': ['open', 'done']
- , sort:
- status: -1
- title: 1
- , (err, todos) ->
+ geddy.model.Todo.all (err, todos) ->
self.respond params: params, todos: todos
add: (req, resp, params) ->
@@ -19,7 +13,6 @@ class Todos
self = this
todo = geddy.model.Todo.create
title: params.title
- id: geddy.string.uuid(10)
status: 'open'
todo.save (err, data) ->
@@ -31,19 +24,18 @@ class Todos
show: (req, resp, params) ->
self = this
- geddy.model.adapter.Todo.load params.id, (err, todo) ->
+ geddy.model.Todo.load params.id, (err, todo) ->
self.respond params: params, todo: todo
edit: (req, resp, params) ->
self = this
- geddy.model.adapter.Todo.load params.id, (err, todo) ->
+ geddy.model.Todo.load params.id, (err, todo) ->
self.respond params: params, todo: todo
update: (req, resp, params) ->
self = this
- geddy.model.adapter.Todo.load params.id, (err, todo) ->
- todo.status = params.status
- todo.title = params.title
+ geddy.model.Todo.load params.id, (err, todo) ->
+ todo.updateAttributes params
todo.save (err, data) ->
if err
@@ -54,7 +46,7 @@ class Todos
remove: (req, resp, params) ->
self = this
- geddy.model.adapter.Todo.remove params.id, (err) ->
+ geddy.model.Todo.remove params.id, (err) ->
if err
params.errors = err
self.transfer 'edit'
View
5 examples/todo_app_coffee/app/models/todo.coffee
@@ -3,9 +3,6 @@ Todo = ->
title:
type: 'string'
required: true
- id:
- type: 'string'
- required: true
status:
type: 'string'
required: true
@@ -16,6 +13,4 @@ Todo = ->
@validatesWithFunction 'status', (status) ->
status == 'open' || status == 'done'
- @adapter = 'mongo'
-
Todo = geddy.model.register 'Todo', Todo
View
9 examples/todo_app_coffee/config/development.coffee
@@ -2,14 +2,11 @@ config =
detailedErrors: false
hostname: null
port: 4000
+ model:
+ defaultAdapter: 'memory'
sessions:
store: 'memory'
key: 'sid'
expiry: 14 * 24 * 60 * 60
- db:
- mongo:
- db: 'todo'
-
-module.exports = config
-
+module.exports = config
View
15 examples/todo_app_coffee/config/development.coffee.mongo
@@ -0,0 +1,15 @@
+config =
+ detailedErrors: false
+ hostname: null
+ port: 4000
+ model:
+ defaultAdapter: 'mongo'
+ db:
+ mongo:
+ dbname: 'model_test'
+ sessions:
+ store: 'memory'
+ key: 'sid'
+ expiry: 14 * 24 * 60 * 60
+
+module.exports = config
View
5 examples/todo_app_coffee/config/init.coffee
@@ -1,8 +1,3 @@
-mongo = require 'mongodb-wrapper'
-
-geddy.db = mongo.db 'localhost', 27017, 'todo'
-geddy.db.collection 'todos'
-
# Add uncaught-exception handler in prod-like environments
if geddy.config.environment != 'development'
process.addListener 'uncaughtException', (err) ->
View
2 lib/app.js
@@ -26,7 +26,6 @@ var fs = require('fs')
, errors = require('./response/errors')
, response = require('./response')
, utils = require('utilities')
- , i18n = require('./i18n')
, init = require('./init')
, helpers = require('./template/helpers')
, actionHelpers = require('./template/helpers/action')
@@ -35,6 +34,7 @@ var fs = require('fs')
, CookieCollection = require('./cookies').CookieCollection
, Request = require('./request').Request
, InFlight = require('./in_flight').InFlight
+ , i18n = utils.i18n
, usingCoffee; // Global variable for CoffeeScript
// Set up a bunch of aliases
View
2 lib/config.js
@@ -39,7 +39,7 @@ config = new (function () {
if (fileBaseName === env || fileBaseName === 'environment') {
if (fileExt === '.coffee') {
// fileName is a CoffeeScript file so try to require it
- useCoffee = useCoffee || file.requireLocal('coffee-script');
+ useCoffee = useCoffee || utils.file.requireLocal('coffee-script');
}
appBaseConfig = require(dir + '/config/environment');
appEnvConfig = require(dir + '/config/' + baseConfig.environment);
View
31 lib/i18n/index.js
@@ -1,31 +0,0 @@
-var i18n = new (function () {
- var _currentLocale = ''
- , _strings = {};
-
- this.getText = function (key, opts, locale) {
- var defaultLocale = geddy.config.i18n.defaultLocale
- , currentLocale = locale || defaultLocale
- , currentLocaleStrings = _strings[currentLocale] || {}
- , defaultLocaleStrings = _strings[defaultLocale] || {}
- , str = currentLocaleStrings[key]
- || defaultLocaleStrings[key] || "[[" + key + "]]";
- for (p in opts) {
- str = str.replace(new RegExp('\\{' + p + '\\}', 'g'), opts[p]);
- }
- return str;
- };
-
- this.loadLocale = function (locale, strings) {
- _strings[locale] = _strings[locale] || {};
- geddy.mixin(_strings[locale], strings);
- };
-
-})();
-
-i18n.I18n = function (controller) {
- this.t = function (key, opts) {
- return i18n.getText(key, opts || {}, controller.locale);
- };
-};
-
-module.exports = i18n;
View
8 lib/init/i18n.js
@@ -1,15 +1,12 @@
-var i18n = require('../i18n')
- , path = require('path')
+var path = require('path')
, fs = require('fs')
, utils = require('utilities')
+ , i18n = utils.i18n
, file = utils.file;
module.exports = new (function () {
var LOCALE_PAT = /([^\/]*).json$/;
- var _loadLocaleData = function (directory, callback) {
- };
-
this.init = function (app, callback) {
var localePaths = [
__dirname + '/../../templates/locales'
@@ -44,6 +41,7 @@ module.exports = new (function () {
};
localePaths = localePaths.concat(geddy.config.i18n.loadPaths || []);
+ i18n.setDefaultLocale(geddy.config.i18n.defaultLocale);
loadLocaleData();
};
View
0 site/css/bootstrap.css → site-old/css/bootstrap.css
File renamed without changes.
View
0 site/css/bootstrap.min.css → site-old/css/bootstrap.min.css
File renamed without changes.
View
0 site/css/bootstrap.min.responsive.css → site-old/css/bootstrap.min.responsive.css
File renamed without changes.
View
0 site/css/bootstrap.responsive → site-old/css/bootstrap.responsive
File renamed without changes.
View
0 site/docs.html → site-old/docs.html
File renamed without changes.
View
0 site/features.html → site-old/features.html
File renamed without changes.
View
0 site/img/glyphicons-halflings-white.png → site-old/img/glyphicons-halflings-white.png
File renamed without changes
View
0 site/img/glyphicons-halflings.png → site-old/img/glyphicons-halflings.png
File renamed without changes
View
0 site/index.html → site-old/index.html
File renamed without changes.
View
0 site/js/bootstrap.js → site-old/js/bootstrap.js
File renamed without changes.
View
0 site/js/bootstrap.min.js → site-old/js/bootstrap.min.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-apollo.js → ...ld/js/google-code-prettify/lang-apollo.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-clj.js → site-old/js/google-code-prettify/lang-clj.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-css.js → site-old/js/google-code-prettify/lang-css.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-go.js → site-old/js/google-code-prettify/lang-go.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-hs.js → site-old/js/google-code-prettify/lang-hs.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-lisp.js → ...-old/js/google-code-prettify/lang-lisp.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-lua.js → site-old/js/google-code-prettify/lang-lua.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-ml.js → site-old/js/google-code-prettify/lang-ml.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-n.js → site-old/js/google-code-prettify/lang-n.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-proto.js → ...old/js/google-code-prettify/lang-proto.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-scala.js → ...old/js/google-code-prettify/lang-scala.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-sql.js → site-old/js/google-code-prettify/lang-sql.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-tex.js → site-old/js/google-code-prettify/lang-tex.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-vb.js → site-old/js/google-code-prettify/lang-vb.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-vhdl.js → ...-old/js/google-code-prettify/lang-vhdl.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-wiki.js → ...-old/js/google-code-prettify/lang-wiki.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-xq.js → site-old/js/google-code-prettify/lang-xq.js
File renamed without changes.
View
0 site/js/google-code-prettify/lang-yaml.js → ...-old/js/google-code-prettify/lang-yaml.js
File renamed without changes.
View
0 site/js/google-code-prettify/prettify.css → ...-old/js/google-code-prettify/prettify.css
File renamed without changes.
View
0 site/js/google-code-prettify/prettify.js → site-old/js/google-code-prettify/prettify.js
File renamed without changes.
View
0 site/tutorial.html → site-old/tutorial.html
File renamed without changes.
View
25 site/app/controllers/application.js
@@ -0,0 +1,25 @@
+/*
+ * Geddy JavaScript Web development framework
+ * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+var Application = function () {
+};
+
+exports.Application = Application;
+
+
+
View
211 site/app/controllers/main.js
@@ -0,0 +1,211 @@
+/*
+ * Geddy JavaScript Web development framework
+ * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*/
+
+var md = require('marked');
+md.setOptions({
+ gfm: true
+, pedantic: false
+, highlight: function (code, lang) {
+ return code;
+ }
+});
+
+var Main = function () {
+
+ this.error = function (req, resp, params) {
+ self.respond(params, {
+ format: 'html'
+ , template: 'app/views/main/error'
+ });
+ };
+
+ this.index = function (req, resp, params) {
+ this.respond(params, {
+ format: 'html'
+ , template: 'app/views/main/index'
+ });
+ };
+
+ this.documentation = function (req, resp, params) {
+ var self = this
+ , docs = []
+ , count = 0
+
+ // once we've got a list of commits, get the tree
+ // for the latest commit
+ , gotCommits = function (err, commits) {
+ var commit = commits[0] && commits[0].commit
+ , url = commit.tree && commit.tree.url;
+ return getTree(url, gotTree);
+ }
+
+ // once we've got the first tree, get 'docs' tree
+ // once we've got the 'docs' tree, call gotTree
+ , getTree = function (url, callback) {
+ var tree;
+ opts.url = url;
+ geddy.request(opts, function (err, trees) {
+ if (err || !trees) {
+ return this.error(req, resp, params);
+ }
+ for (var i in trees.tree) {
+ tree = trees.tree[i];
+ if (tree.path == 'docs') {
+ return getTree(tree.url, gotTree);
+ }
+ }
+ return callback(err, trees.tree);
+ });
+ }
+ , getBlob = function (paths, i, callback) {
+ var options = {
+ url: paths[i].url
+ , dataType: 'json'
+ }
+ geddy.request(options, function (err, resp) {
+ var content = new Buffer(resp.content, 'base64').toString('utf8')
+ , name = paths[i].path.replace('.md','')
+ , subs = []
+ , lines = content.split('\n');
+ for (var l in lines) {
+ if (lines[l].indexOf('#### ') == 0) {
+ subs.push(geddy.string.trim(lines[l].replace('#### ', '')));
+ }
+ }
+ docs[parseInt(name[0]) - 1] = {
+ name: name.split('-')[1]
+ , content: md(content)
+ , subs: subs
+ };
+ return respond(paths.length);
+ });
+ }
+
+ // once we've got the 'docs' tree,
+ // parse it and call getBlob for each file
+ , gotTree = function (err, tree) {
+ for (var i in tree) {
+ getBlob(tree, i, respond);
+ }
+ }
+
+ // once we've got everything done, respond with data
+ , respond = function (total) {
+ count++;
+ if (count == total) {
+ self.respond({docs: docs}, {
+ format: 'html'
+ , template: 'app/views/main/documentation'
+ });
+ }
+ }
+
+ // inital call to get the commits
+ , opts = {
+ url<