Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 680 lines (544 sloc) 22.877 kB
6c37227 @Techwraith docs page is done, community page is doneish, starting on tutorial
Techwraith authored
1 ### Introduction
2
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
3 In this tutorial we'll learn how to use Geddy by creating a simple todo
4 manager applciation. We will create two applications one using
5 scaffolding and one using resources. See the [finished
6 version](https://github.com/mde/geddy/tree/master/examples/todo_app).
6c37227 @Techwraith docs page is done, community page is doneish, starting on tutorial
Techwraith authored
7
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
8 #### In this tutorial we'll cover:
6c37227 @Techwraith docs page is done, community page is doneish, starting on tutorial
Techwraith authored
9
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
10 - Creating a Geddy application
11 - Learning how to use the Geddy executable
12 - Using Geddy models
13 - How views in Geddy work
14 - How to use controllers to tie everything together
15
b7f73db @Techwraith tutorial fixes
Techwraith authored
16 ### Installation
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
17
18 If you haven't already, install [Node](http://nodejs.org#download) on
19 your machine.
20
21 Next, install Geddy from [NPM](http://npmjs.org/), this will also
22 install [Jake](https://github.com/mde/jake):
23
24 ```bash
25 $ [sudo] npm install -g geddy
26 ```
27
28 We need to install it globally (-g) so we can use geddy generators or
29 start the server. More on this later. Note: installing packages globally
30 may require super-user access.
31
32 #### Using the Geddy command
33
34 Now that we have Geddy installed we need to learn how to use its command
35 from the CLI. There are a few commands and options that help with the
36 development process of creating applications using Geddy. Here we will
37 go over what each of them do. Note if no arguments are given Geddy will
38 start up the server if it's a Geddy application, otherwise it will show
39 the help dialog.
40
41 #### Options:
42
43 - `--environment`, `-e`: Environment to use
44 - `--port`, `-p`: Port to connect server to
45 - `--workers`, `-w`: Number of workers to use (default: 1)
46 - `--debug`, `-d`: Sets the log level to output debug messages to
47 console
48 - `--jade`, `-j`: When generating views, use Jade templates(Default:
49 EJS)
50 - `--handle`, `-H`: When generating views, use Handlebars
51 templates(Default: EJS)
52 - `--mustache`, `-m`: When generating views, use Mustache
53 templates(Default: EJS)
54 - `--version`, `-v`: Output the version of Geddy installed
55 - `--help`, `-h`: Output the list of commands and options
56
57 #### Commands:
58
59 - `app <name>`: Create a new Geddy application
60 - `resource <name> [model attributes]`: Create a new Geddy resource.
61 Resources include a model, controller and a route
62 - `scaffold <name> [model attributes]`: Creates a new Geddy
63 scaffolding. Scaffolding includes everything Resources have as well
64 as views
65 - `secret`: Generate a new application secret in
66 \`config/environment\`
67 - `controller <name>`: Generate a new controller including an index
68 view and a route
69 - `model <name> [model attributes]`: Generate a new model
70 - `console`: opens a console in the context of geddy
71
72 #### How to use Geddy commands
73
74 Each of Geddy's commands(`app`, `resource`, `controller`, etc.) take a
75 command or set of commands(excluding `secret` and `console`). Here we'll
76 learn how to use those commands.
77
78 - `app` takes a single argument being the name you'd like, then it
79 will generate a base application. If no name is given the command
80 will fail.
81 - `secret` doesn't take any arguments, it will find your
82 `config/environment` file and create a new secret in it deleting any
83 other secret.
84 - `controller` takes a single argument being a name. It will create a
85 new controller, a route and an index view. If you also include the
86 options `--jade`, `--handle` or `--mustache` you can substitute the
87 template language to your liking.
88 - `model` takes one or more arguments, the first being a name and the
89 others being a set of model properties. We won't go over model
90 properties right now but you can learn about them in the next
91 section. This will create a new model including the model properties
92 given.
93 - `resource` takes one or more arguments, the first being a name and
94 the others being a set of model properties. This will create a
95 controller, a model including the given model properties and a
96 resource route.
97 - `scaffold` takes one or more arguments, the first being a name and
98 the others being a set of model properties. Scaffolding includes a
99 controller, a model including the given model properties as well as
100 a default model adapter a resource route and will create all views.
101 If you also include the options `--jade`, `--handle` or `--mustache`
102 you can substitute the template language to your liking.
103 - `console` doesn't take any arguments, it will start a geddy console.
104
105 #### Model properties
106
107 There are a three commands(`resource`, `model` and `scaffold`) that also
108 include model property arguments. This is a list seperated by spaces
109 that include the property, its type and an optional default setting.
110 Below are some examples of how they are used in the commands.
111
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
112 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
113 $ geddy scaffold user name:string
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
114 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
115
116 The example above will create our normal scaffolding and include a
117 `name` property of type `string`. If no type is given it will default to
118 `string`.
119
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
120 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
121 $ geddy scaffold user name:default
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
122 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
123
124 This example creates scaffolding but includes `name` as the default
125 property that will be used when displaying the content in the views. In
126 this example the property `name` is given the type `string` because no
127 type was given, you could of also writte `name:string:default`, or you
128 could've used a different type of course. The `default` setting also
129 includes an alias called `def`. If no default property is given Geddy
130 will use `id` as the display property.
131
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
132 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
133 $ geddy scaffold user name:default id:int
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
134 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
135
136 This time we used `name` type `string` as the default property. We also
137 overwrote the included `id` property with a different type (by default
138 it's a string).
139
140 Note: an ID property will *always* be created.
141
1cc244c @Techwraith tutorial fixes
Techwraith authored
142 ### With scaffolding
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
143
144 This will be a short tutorial as scaffolding will do almost everything
145 for us, I won't go into detail on what it does as it will be covered in
146 exstensive detail in the [resources tutorial](#resources). The source
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
147 for this tutorial can be found
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
148 [here](https://github.com/mde/geddy/tree/master/examples/todo_app).
149
150 First we'll create our application, this will create a base so we can
151 start on.
152
a4398bd @Techwraith fixed some style issues again
Techwraith authored
153 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
154 $ geddy app todo_app
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
155 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
156
157 Let's spend some time reviewing what geddy did. The previous command
158 created a lot. During the tutorial we will edit and review some of this
159 files, but we'll briefly explain what they are now so you get familiar
160 with the base application.
161
162 - `app/controllers`: contains the base controller and the main
163 controller. All controllers will go in this folder
164 - `app/views/layouts/application.html.ejs`: layout used by default by
165 all the views
166 - `app/views/main/index.html.ejs`: main view displayed when you visit
167 the root of your web application
168 - `config/development.js`: configuration for the development
169 environment
170 - `config/environment.js`: configuration for all your environments
171 - `config/init.js`: this is where you write code that will be run only
172 once your app starts.
173 - `config/production.js`: configuration for the production environment
174 - `config/router.js`: contains route settings. It has some examples
175 and you can learn more about [routes from the
176 Wiki.](https://github.com/mde/geddy/wiki/Using-the-Router)
177 - `public/`: contains static assets that will be served directly by
178 geddy's server
179 - `public/css/`: Geddy uses [twitter
180 bootstrap](http://twitter.github.com/bootstrap/). These are
181 referenced by the layout file (`application.html.ejs`)
182 - `public/img/`: contains a few images used by twitter bootstrap. Your
183 images will usually go here as well
184 - `public/js/`: bootstrap and jquery scripts
185
186 Now from your app's root simply start geddy
187
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
188 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
189 $ cd todo_app
190 $ geddy
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
191 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
192
193 Then open your browser to [localhost:4000](http://localhost:4000/), and
194 you'll find the hello world page.
195
196 So now we want to create a scaffold to manage our todo items. We will
197 create a title and status property so that we have some attributes to
198 use.
199
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
200 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
201 $ geddy scaffold todo title:default status
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
202 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
203
204 We are almost done. Now you have to restart geddy
205
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
206 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
207 $ geddy
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
208 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
209
210 Open your browser to [localhost:4000/todos](http://localhost:4000/todos)
211 and you'll get a list of the todos which should be empty. Go ahead and
212 look around, you can create show edit and delete todo items. We're going
213 to make a few changes though.
214
215 The first thing we'll do is to add some validation to our Todo model. So
216 open 'app/models/todo.js' in your editor and add the following lines
217 anywhere inside the constructor function
218
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
219 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
220 var Todo = function () {
221 ...
222 // Add this inside the constructor function
223 this.validatesPresent('title');
224 this.validatesLength('title', {min: 5});
225
226 this.validatesWithFunction('status', function (status) {
227 return status == 'open' || status == 'done';
228 });
229 ...
230 };
231 Todo = geddy.model.register('Todo', Todo);
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
232 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
233
234 Here we are making it so the title property is required and have a
235 minumum of 5 characters. We also made it so the status acts like a
236 boolean attribute but uses custom names instead of true/false. We should
237 also change our `edit` and `add` views to limit the options, but we will
238 do it as part of the [resources tutorial](#resources), for now we will
239 leave the views the way they are.
240
241 Now that we've made the needed changes, restart Geddy to update our
242 model changes. Go and play with the app again, create a todo item, try
243 to edit and test the validation rules. We've got a good todo application
244 running and didn't really have to do much. Scaffolding is very good when
245 you need something simple to get you started. To learn more about
246 controllers and views keep reading and follow the [resources
247 tutorial](#resources).
248
1cc244c @Techwraith tutorial fixes
Techwraith authored
249 ### Without scaffolding
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
250
251 Let's start by using the `geddy` executable to generate a basic
252 app-structure.
253
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
254 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
255 $ geddy app todo_app
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
256 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
257
258 Now let's try out our new application by running geddy from your
259 application's root
260
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
261 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
262 $ cd todo_app
263 $ geddy
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
264 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
265
266 Your app should be running on port 4000. Visit
267 [http://localhost:4000](http://localhost:4000) in your browser to see
268 your app.
269
270 #### Optional: check out your app on a mobile phone
271
272 - point your mobile phone's browser to your computer on port 4000
273 - OR open up your favorite phone simulator and go to
274 [http://localhost:4000](http://localhost:4000)
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
275 - OR resize your browser to at most 480px wide
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
276
a99b037 @Techwraith tutorial fixes
Techwraith authored
277 ### Resource
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
278
279 Now, let's get started building our To Do list manager. First, we'll
280 need to generate the `todo` resource. We do this using the `geddy`
281 executable as well:
282
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
283 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
284 $ geddy resource todo title:string status
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
285 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
286
287 What did that do?
288
289 - It generated a `todo` model including the given model properties
290 - It generated a `todos` controller
291 - It created a `todos` view directory. Please note the folder is empty
292 since resource won't generate any views for you.
293 - It generated these routes from a resource route:
294 - `/todos` (GET)
295 - `/todos` (POST)
296 - `/todos/add` (GET)
297 - `/todos/:id/edit` (GET)
298 - `/todos/:id` (GET)
299 - `/todos/:id` (PUT)
300 - `/todos/:id` (DELETE)
301
b7f73db @Techwraith tutorial fixes
Techwraith authored
302 ### Views
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
303
304 To start creating our views, create a few files in `app/views/todos`,
305 those being:
306
307 - `_form.html.ejs`
308 - `add.html.ejs`
309 - `edit.html.ejs`
310 - `index.html.ejs`
311 - `show.html.ejs`
312
313 We won't go into to much detail here, as it should be pretty self
314 explanatory but I'll go through some things.
315
316 First we'll create the `_form.html.ejs` partial template, this will hold
317 all the form data for edit and add actions .
318
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
319 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
320 <%
321 var isUpdate = params.action == 'edit'
322 , formTitle = isUpdate ? 'Update this To Do Item' : 'Create a new To Do Item'
323 , action = isUpdate ? todoPath(params.id) + '?_method=PUT' : todosPath
324 , deleteAction = isUpdate ? todoPath(params.id) + '?_method=DELETE' : ''
325 , btnText = isUpdate ? 'Update' : 'Add'
326 , doneSelectAttributes = isUpdate && todo.status === 'done' ? "selected=true" : ''
327 , openSelectAttributes = isUpdate && todo.status === 'open' ? "selected=true" : ''
328 , titleValue = isUpdate ? todo.title : ''
329 , errors = params.errors;
330 %>
331 <form id="todo-form" class="form-horizontal" action="<%= action %>" method="POST">
332 <fieldset>
333 <legend><%= formTitle %></legend>
334 <div class="control-group">
335 <label for="title" class="control-label">Title</label>
336 <div class="controls">
337 <%- contentTag('input', titleValue, {type:'text', class:'span6', placeholder:'enter title', name:'title'}) %>
338 <% if (errors) { %>
339 <p>
340 <% for (var p in errors) { %>
341 <div><%= errors[p]; %></div>
342 <% } %>
343 </p>
344 <% } %>
345 </div>
346 </div>
347 <% if (isUpdate) { %>
348 <div class="control-group">
349 <label for="status" class="control-label">Status</label>
350 <div class="controls">
351 <select name="status" class="span6">
352 <option <%=openSelectAttributes%>>open</option>
353 <option <%=doneSelectAttributes%>>done</option>
354 </select>
355 </div>
356 </div>
357 <% } %>
358 <div class="form-actions">
359 <%- contentTag('input', btnText, {type: 'submit', class: 'btn btn-primary'}) %>
360 <% if (isUpdate) { %>
361 <%- contentTag('button', 'Remove', {type: 'submit', formaction: deleteAction, formmethod: 'POST', class: 'btn btn-danger'}) %>
362 <% } %>
363 </div>
364 </fieldset>
365 </form>
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
366 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
367
368 Here we created a couple variables so we can tell if it's for a edit or
369 add action, then if we have any errors we dislay them. Also we are using
370 a couple view helpers (contentTag) which are helpful with dealing with
371 assets, links, etc. You can read more about our view helpers
372 [here](https://github.com/mde/geddy/wiki/View-Helpers).
373
374 Now that we've created a base for our add and edit actions, we'll do
375 them now. They're simple they just use the \_form partial. Add the
376 following code to `add.html.ejs`
377
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
378 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
379 <div class="hero-unit">
380 <%= partial('_form', {params: params}); %>
381 </div>
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
382 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
383
384 The edit view is slightly different because we will need to pass the
385 todo object to the partial. Modify `app/views/todos/edit.html.ejs` with
386 the following code:
387
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
388 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
389 <div class="hero-unit">
390 <%= partial('_form', {params: params, todo: todo}); %>
391 </div>
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
392 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
393
394 Now that we have views that will create todo items let's add a simple
395 `show.html.ejs` just so we can test everything end to end. In the
396 following code I just loop through the params.
397
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
398 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
399 <div class="hero-unit">
400 <%- linkTo('Edit this todo', editTodoPath(params.id), {class: 'btn pull-right'}); %>
401 <h3>Params</h3>
402 <ul>
403 <% for (var p in todo) { %>
404 <li><%= p + ': ' + params[p]; %></li>
405 <% } %>
406 </ul>
407 </div>
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
408 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
409
410 Finally we need to create the index action to link everything together.
411
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
412 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
413 <div class="hero-unit">
414 <h2>To Do List</h2>
415 <%- linkTo('Create a new To Do', addTodoPath, {class: 'btn pull-right'}) %>
416 </div>
417 <% if (todos && todos.length) { %>
418 <% for (var i in todos) { %>
419 <div class="row todo-item">
420 <div class="span8">
421 <h3><%- linkTo(todos[i].title, todoPath(todos[i].id)) %></h3>
422 </div>
423 <div class="span4"><h3><i class="icon-list-alt"></i><%= todos[i].status; %></h3></div>
424 </div>
425 <% } %>
426 <% } %>
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
427 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
428
429 For the index action we just have a link to add new items, and a list of
430 all the items, with a link to each of their edit paths. If you notice
431 we're using special helpers here, that create links to the path
432 specified.
433
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
434 ### Model
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
435
436 We're ready to start in on modeling our data. Geddy provides us with
437 some pretty cool tools to do this:
438
439 - Validation
440 - Typed Data
441 - Instance Methods
442 - Static Methods
443
444 These tools should look somewhat familiar to anyone who's used an
445 ORM-system like Ruby's ActiveRecord, or DataMapper.
446
447 Go ahead and open up `app/models/todo.js`. Read through the commented
448 out code there for some ideas on what you can do with models. We'll be
449 writing our model from scratch for this tutorial, so let's leave that
450 commented out.
451
452 So, minus the commented out code, you should have a file that looks like
453 this:
454
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
455 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
456 var Todo = function () {
457
458 this.defineProperties({
459 title: {type: 'string'}
460 , status: {type: 'string'}
461 });
462
463 };
464
465 Todo = geddy.model.register('Todo', Todo);
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
466 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
467
468 The `defineProperties` method takes any number of properties to be added
469 to the model. The keys in the object will be added as properties on the
470 model. The values are just objects that describe the properties. When we
471 ran the scaffold command it created these for us. But we want to change
472 it so they are all \`required\`. To learn more, check out the
473 [readme](https://github.com/mde/geddy/blob/master/README.md).
474
475 There's also a more detailed validation API. While we're here, let's add
476 some validation as well. The final code should look like this:
477
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
478 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
479 var Todo = function () {
480
481 this.defineProperties({
482 title: {type: 'string'}
483 , status: {type: 'string'}
484 });
485
486 this.validatesPresent('title');
487 this.validatesLength('title', {min: 5});
488
489 this.validatesWithFunction('status', function (status) {
490 return status == 'open' || status == 'done';
491 });
492 };
493
494 Todo = geddy.model.register('Todo', Todo);
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
495 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
496
497 For the `title` property, we made sure that the property is always
498 present and we made sure that the `title` property is a minimum of 5
499 characters long.
500
501 For the `status` property, we used a function to validate that the
502 property is always set to either `open` or `done`.
503
504 For more information about Geddy's Models, you can check out the [Model
505 wiki page](https://github.com/mde/geddy/wiki/Models).
506
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
507 #### Model-adapter
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
508
509 Now that we've set up our `todo` model, we need to define a way to store
510 it. To keep our models persistance agnostic, Geddy uses model-adapters.
511 By default it will store objects in memory using the `memory` model
512 adapter. You can change the default memoryAdapter in
513 `config/development.js`.
514
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
515 ```
516 defaultAdapter: 'memory'
517 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
518
519 Now we've got a place to store our `todo`'s. This is in your
520 application's memory, so it will disappear when you restart the server.
521
522 #### Optional: use mongo for persistence
523
524 Install a [mongodb](http://www.mongodb.org/downloads) server if you
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
525 haven't already and ` $ [sudo] npm install [-g] mongodb-wrapper` to
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
526 install the required mongodb-wrapper and set `defaultAdapter = 'mongo'`
527 in config/development.js instead of the memory adapter. You will also
528 have to specify the db configuration
529 `db: { mongo: { dbname: 'model_test' }`. For more information see the
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
530 [Model API reference](/documentation#models)
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
531
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
532 ### Controller
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
533
534 Controllers sit between the views and models. They are also the entry
535 point of our code. When a user gets a page a function in a controller,
536 also called a controller acton, will get invoked. The controller will
537 usually interact with the model and pass it to the view. The pattern
538 isn't as black and white, but for the purpose of the tutorial, let's
539 move on to actually write some controller actions.
540
541 #### Saving todos
542
543 To save a todo we need to edit the `create` action in
544 `app/controllers/todos.js`. It's not doing much at the momment so lets
545 modify it a little bit.
546
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
547 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
548 this.create = function (req, resp, params) {
549 var self = this
550 , todo = geddy.model.Todo.create({title:params.title, status:'open'});
551
552 todo.save(function(err, data) {
553 if (err) {
554 params.errors = err;
555 self.transfer('add');
556 } else {
557 self.redirect({controller: self.name});
558 }
559 });
560 };
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
561 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
562
563 First, we create a new instance of the `Todo` model with
564 `geddy.model.Todo.create`, passing in the title that our form will post
565 up to us, and setting up the default status.
566
567 Then we call we call the `save` method. Internally, save does two
568 things. It validates the model based on the rules we defined earlier.
569 This is similar to calling `todo.isValid()`. If the model was valid, it
570 will delegate to the model adapter configured previously to actually
571 persist the model. If either step fails, you will get an error
572 collection as the first parameter of the function and we redirect the
573 user back to the /todos/add route. Otherwise we redirect to the
574 controller's default action `self.redirect({controller: self.name});`.
575
576 #### Listing all todos
577
578 Now that we we can create To Do items, we should probably list them
579 somewhere. Lets change the `index` action in the `todos` controller.
580
581 Open up `/app/controllers/todos.js` again and replace the current
582 implementaton with the following code.
583
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
584 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
585 this.index = function (req, resp, params) {
586 var self = this;
587
588 geddy.model.Todo.all(function(err, todos) {
589 self.respond({params: params, todos: todos});
590 });
591 };
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
592 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
593
594 This part is a bit simpler and it follows a similar pattern. Instead of
595 calling create in `geddy.model.Todo` this time we simply call `all` and
596 we pass the data back to the view for rendering
597
598 Now that we can can load todo items you can test it by starting up Geddy
599 and going to [localhost:4000/todos](http://localhost:4000/todos) and you
600 can view the list of items.
601
602 #### Showing a todo
603
604 Now that we have our index action working as expected, we should work on
605 the `show` controller action to display todo details.
606
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
607 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
608 this.show = function (req, resp, params) {
609 var self = this;
610
611 geddy.model.Todo.load(params.id, function(err, todo) {
612 self.respond({params: params, todo: todo});
613 });
614 };
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
615 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
616
617 Now we have a working show action in the controller to load items.
618
619 #### Updating a todo
620
621 Alright, now that we can view our todos let's edit the `update` and
622 `edit` actions in the `todos` controller. They should look something
623 like this:
624
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
625 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
626 this.edit = function (req, resp, params) {
627 var self = this;
628
629 geddy.model.Todo.load(params.id, function(err, todo) {
630 self.respond({params: params, todo: todo});
631 });
632 };
633
634 this.update = function (req, resp, params) {
635 var self = this;
636
637 geddy.model.Todo.load(params.id, function(err, todo) {
638 todo.updateAttributes(params);
639
640 todo.save(function(err, data) {
641 if (err) {
642 params.errors = err;
643 self.transfer('edit');
644 } else {
645 self.redirect({controller: self.name});
646 }
647 });
648 });
649 };
ada62c7 @Techwraith formatting changes for the tutorial
Techwraith authored
650 ```
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
651
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
652 #### Deleting a todo
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
653
654 The delete is really simple specially now that you're familiar with the
655 pattern. This time you will have to call remove passing the id of the
656 todo you want to delete. We will leave the details as an excercise.
657 Remember that you can always compare your solution to the [final
658 version](https://github.com/mde/geddy/tree/master/examples/todo_app).
659
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
660 ### API
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
661
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
662 Check these urls out in your browser:
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
663
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
664 - GET: `localhost:4000/todos.json`
665 - GET: `localhost:4000/todos/:id.json`
666 - POST: `localhost:4000/todos`
667 - PUT: `localhost:4000/todos/:id`
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
668
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
669 ### Conclusion
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
670
4ce6f02 @Techwraith tutorial fixes
Techwraith authored
671 At this point you should have a working To Do List app!
90d1ab9 @Techwraith ported most of the tutorial over
Techwraith authored
672
673 If you want to explore a little more, here are some other things you
674 could do:
675
676 - Change the `Main#index` route to point to the `Todos#index` action
677 (hint, check out `config/router.js`)
678 - Add some logging with `geddy.log`
679 - Configure mongo, riak or postgress and use it instead of the memory
680 modelAdapter. See how easy it's to switch
Something went wrong with that request. Please try again.