首页 > 代码库 > 以ToDoList应用来学习Geddy
以ToDoList应用来学习Geddy
Geddy学习笔记
初始工具安装 Node.js, Geddy, Jake
本文运行环境为Windows,Node.js安装比较简单,进入Node.js官网直接下载安装包傻瓜安装即可。
安装Geddy,打开终端cmd.exe,输入$ npm install -g geddy
安装Jake,输入 $ npm install -g geddy jake
geddy gen命令
应用例子:
$ geddy gen scaffold book title:string descrption:text $ geddy gen scaffold user name:default
Geddy的生成器命令包括有:
app
secret
scaffold [model properties]
resource [model attributes]
controller
model [model attributes]
其中,这三个命令‘scaffold‘, ‘resource‘, ‘model‘包括以空格分隔的Model属性
构建一个App
新建工作目录,进入目录路径,
敲入命令:$ geddy gen app to_do
生成文件夹及文件,具体含义请参考http://geddyjs.org/tutorial#building_an_app
现在打开你简单的初级geddy应用:
$ cd to_do $ geddy
之后打开浏览器输入 ,你就进入hello world页面了
创建“资源”
现在我们为ToDo项目创建“资源”,ToDo项目包括title, status
$ geddy gen scaffold to_do title:default status
创建后,再重新打开cmd,重启Geddy:
$ geddy
再打开浏览器到 (URL地址就是在后面加个 app name 多个s),然后我们就看到ToDoList的App页面了
添加验证功能
在项目里打开 ‘app/model/to_do.js‘ ,添加以下代码对title, status进行验证:
var ToDo = function(){ ... this.validatesPresent(‘title‘), this.validatesLength("title", {min: 5}); this.validatesWithFunction(‘status‘, function(status){ return ‘open‘ === status || ‘done‘ === status; }, {message: "Status must be ‘open‘ or ‘done‘."}); ... }; ToDo = geddy.model.register("ToDo", ToDo);
代码很简单,大家测试一下ToDoList的App,添加和编辑ToDo项目
创建关联
现在我们创建另外一个“资源”,使它关联到我们的ToDos。
假设ToDo项目有几个步骤才行完成创建的,现在我们就scaffold out步骤“资源”:
$ geddy gen scaffold step title:default description:text status
添加步骤验证
现在我们可以关联步骤和ToDo项目了。接着我们添加每个步骤都必须有一个‘title‘的验证——添加以下代码到你的步骤模型里(app/models/step.js):
var Step = function(){ ... this.validatesPresent(‘title‘), // 同ToDo的验证一样 this.validatesLength("title", {min: 5}); this.validatesWithFunction(‘status‘, function(status){ return ‘open‘ === status || ‘done‘ === status; }, {message: "Status must be ‘open‘ or ‘done‘."}); ... }; Step = geddy.model.register("Step", Step);
创建关联
现在我们为创建的ToDo和Step俩模型创建关联。
添加下面代码到ToDo模型里:
var ToDo = function () { ... this.hasMany(‘Steps‘); ... }; ToDo = geddy.model.register(‘ToDo‘, ToDo);
这表明一个ToDo可以有多个关联的Step(1对n)。
接着,添加下面代码到Step模型里:
var Step = function () { ... this.belongsTo(‘ToDo‘); ... }; Step = geddy.model.register(‘Step‘, Step);
这表明每一个Step都会被一个ToDo拥有。(1对1)
显示关联
打开 可看到Steps的空列表。
然后虽然我们可以添加Step,但没有选项给我们选择关联的ToDo项目。
下面让我们来修复这个问题,思路是获取ToDos里的数据,然后加载到页面中一个下拉框供选择。
获取ToDos
用编辑器打开 ‘app/controllers/steps.js‘ ,看到 ‘add‘ 动作( this.add
,Step Controller的一个方法)。
接着,我们用Geddy ORM的 all
方法去获取之前添加的ToDos项目。这个在渲染Step编辑页面之前完成:
this.add = function (req, resp, params) { var self = this; geddy.model.ToDo.all(function(err, data){ if(err) throw err; self.respond({params: params, toDos: data}); }); };
上面获取ToDo项目的数据了,并在回调函数中作为 toDos
参数传到Step的‘编辑‘页面。
传递数据给表单
打开 app/views/steps/add.html.ejs
。这是一个被 ‘add‘ 添加和 ‘edit‘ 编辑页面共享的表单,它被渲染为一个 ‘partial‘。
现在需把ToDos的数据传给 ‘partial‘ ,在 ‘partial‘ 那行,把该行代码改为这样:
<%- partial(‘form‘, {step:{}, toDos: toDos}) %>
显示ToDos在下拉框中
现在我们打开 ‘partial‘ 模板 ‘app/views/steps/form.html.ejs‘ ,我们准备把ToDos的数据扔到一个下拉框里。
Geddy有很多好用方便的助手工具,比如 selectTag
,和其他好多好多。你可以参考 助手工具文档。
在div.control-group里,如下添加下拉框:
<label for="title" class="control-label">To-Do for this step</label> <div class="controls"> <%- selectTag(toDos, step.toDoId, { name: ‘toDoId‘ , valueField: ‘id‘ , textField: ‘title‘ }); %> </div>
第二个参数 step.toDoId
指定哪个元素会被默认选择。这个现在还没起作用,但在我们开始编辑Steps时它就有效了。
保存Step
这时创建一个新的Step,看看它有没toDoId(与相关的ToDo项目的ID对应),如果有的话就表示关联正确,若冇则否。
编辑Step
与前面调整 ‘add‘ 执行动作一样,这里也要调整 ‘edit‘ 执行动作。打开Step Controller,更改 ‘edit‘ 如下:
this.edit = function (req, resp, params) { var self = this; geddy.model.Step.first(params.id, function(err, step) { if (err) { throw err; } if (!step) { throw new geddy.errors.BadRequestError(); } else { geddy.model.ToDo.all(function (err, data) { if (err) { throw err; } self.respond({step: step, toDos: data}); }); // self.respondWith(step); } }); };
重要提示:原来的 respondWith
方法被替换为低级的 respond
了。当你只有一个model的实例时,使用 respondWith
方法是很方便的,但这里要传递一些数据,所以要用 respond
方法。
点击这里 学习更多响应请求的方法。
现在打开 ‘app/views/steps/edit.html.ejs‘ ,传递 toDos
给 ‘partial‘ :
<%- partial(‘form‘, {step: step, toDos: toDos}) %>
。
现在创建更多的Step,并把它们关联到同一个ToDo项目。这时,我们也要关注另一个问题:在ToDo项目视图下显示所有的Step。
在toDo这边的关联
打开ToDo的Controller ‘app/controllers/to_dos.js‘,更新 ‘show‘ 执行动作来获取所有与某特定的ToDo项相关的Steps:
this.show = function (req, resp, params) { var self = this; geddy.model.ToDo.first(params.id, function(err, toDo) { if (err) { throw err; } if (!toDo) { throw new geddy.errors.NotFoundError(); } else { toDo.getSteps(function (err, data) { self.respond({toDo: toDo, steps: data}); }); } }); };
注意到上面代码的 first
执行来获取第一个匹配特定id的ToDo项目。而注意到toDo实例有 getSteps
的方法来获取相关联的Steps数据,这是Geddy提供的方便方法:如果ToDo设置了 hasMany
的 ‘Zoobie‘ 的项目,Geddy会自动生成 getZoobies
方法来获取它们。
另外,至于 respondWith
方法被替换为 respond
,这个的原因和作用前面已提及。
现在,打开 ‘show‘ 视图(app/views/to_dos/show.html.ejs),再修改下。
底部的代码通过遍历toDo的属性来检验该项是否已经被保存了,但这个是默认生成的不起作用的代码,我们把它替换为以下的内容:
<h3>Status: <%= toDo.status %></h3> <h3>Steps</h3> <% steps.forEach(function (step) { %> <h4> <%- linkTo(step.title, {controller: ‘steps‘, action: ‘show‘, id: step.id}); %> </h4> <% }); %>
代码遍历该ToDo项关联的Steps,生成以step的title为文字、和链接到step的 ‘show‘ 执行动作的url的链接。
API
检验下以下的url:
- GET:
localhost:4000/to_dos.json
(ToDo项目列表,JSON字符串显示) - GET:
localhost:4000/to_dos/:id.json
(id为:id的toDo的详情,包括steps,JSON字符串显示) - POST:
localhost:4000/to_dos
(页面显示) - PUT:
localhost:4000/to_dos/:id
(页面显示)
总结
现在你已经完成了一个ToDoList的Geddy应用。如果你想探索更多,可以试下:
- 改变
Main#index
路由为ToDos#index
(提示:check out ‘config/router.js‘) - 利用
geddy.log
添加一些log - 配置 ‘mongo‘, ‘riak‘ 或者 ‘postgress‘ 来替换memory modelAdapter,你会发现它是非常容易转换的