七周七Web开发框架

978-7-115-38843-8
作者: 【美】Jack Moffitt
译者: 张霄翀邱俊涛孙镌宸顾宇
编辑: 陈冀康

图书目录:

详情

本书介绍了7种对现代Web应用和Web开发产生重大影响的开发框架,它们是Sinatra, CanJS, AngularJS, Ring, Webmachine, Yesod, Immutant。每种框架在构建app方面都有其独特的思路和强大的功能特色。本书延续了畅销书《七周七语言》和《七周七数据库》的写作风格和体例,将进一步拓展七周系列的品牌和影响力。

图书摘要

Simplified Chinese-language edition Copyright © 2015 by Posts & Telecom Press. All rights reserved.

Copyright © 2014 The Pragmatic Programmers, LLC. Original English language edition, entitled Seven Databases in Seven Weeks.

本书中文简体字版由The Pragmatic Programmers, LLC授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

版权所有,侵权必究。

 

本书带领读者认识和学习7种影响现代Web应用并改变了Web开发方式的框架,以期给Web开发者带来启发和思考。

本书延续了同系列的畅销书《七周七语言》和《七周七数据库》的体例和风格。全书共8章,前7章介绍了Sinatra、CanJS、AngularJS、Ring、Webmachine、Yesod和Immutant共计7种Web开发框架,最后一章总结回顾了所有的知识点。书中对每一种框架的介绍,都为构建Web应用带来了独特而强大的思路。除此之外,书中还提供了一系列代码示例和在线资源以供参考。

本书适合有一定基础的Web开发人员阅读,能够帮助读者拓宽思路,激发更多的设计灵感。

 

2003 年,我带着家人乘坐去往科罗拉多州杜兰戈市的火车。在寸土寸金的年代里,狭窄的红色砂崖中狭窄的轨距曾经运转良好。而现在,火车变成了历史的遗迹,已经完全被更安全高效的汽车、飞机所取代。逝者如斯。

今天也一样,我们见证了变革。单核的计算机已死,或者正在死去。不错,作为它们的继承者,多核技术是一个奇迹。同时,它们也是一个巨大的技术挑战。我们已经熟知且依赖的编程语言不再按照预期的工作了,结果就是我们看到了新一代的编程语言正在诞生。到目前为止,还没有好心人宣布获胜者。

在这个背景下,我在2010年编写了《七周七语言》这本书。说实话,我没有期望会卖多少本。毕竟那只是一个在Java世界中讨论各种语言的书,也是一本在一切都被面向对象所控制的世界中讨论多种编程范式的书而已。但是程序员逐渐意识到了技术停滞带来的危险,并且接受学习编程语言是为了让人更聪明,从而能够更好地应对变化的理念。从这个方面来看,那本书是一个巨大的成功。

三年过去了,虽然函数式编程已经开始获得一些关注,但是仍然没有领导者。我们发现,多年之前扔进我们虚拟池中的多核芯片开始荡起一些涟漪。

仅仅将去年的窄轨道拓宽是不够的。在本书中,Fred和Jack会向你展示前沿的人们如何将Web开发朝着它本应该的方向上发展。你会看到一个叫作Sinatra的传统的面向对象框架,然后你会朝着客户端进发,那里JavaScript正在编织传奇。你将会通过CanJS和AngularJS来学习如何实现完整的、富客户端的开发。接下来,你将进入服务器端,看看函数式编程的强大能力。你会遇到两个Clojure的框架:极简主义的Ring和以健壮著称的Immutant。你会看到Erlang中基于状态机的Webmachine。如果这还不足以颠覆你的想法,你会发现强大到不可思议的Haskell框架Yesod。

“七周七某某”这套书就是用来拓展你的思维的。我非常自豪地为你带来这个系列的下一本:《七周七Web开发框架》。衷心地希望本书能带你超越任何阻碍。

谨致问候

Bruce Tate

首席技术官,icanmakeitbetter.com

 

Q:你们为什么要写这本书?

Jack:解决问题的方法有很多种,而程序员不断地开发出新技术,构建出新语言以找到更好的解决方案。在编程的不同方面存在众多不同的想法,多年来,在感受过多次大开眼界的震撼之后,我很想与人分享自己的经历。

构建一个Web应用的方式不止一种,甚至连我自己经手过的项目都没有哪两个用的是同样的方式开发的。Web编程拥有数百种可供选择的框架和库,而传统的GUI编程却只有屈指可数的几种选择。如此多的可能性,却没有哪个是完美的,所以我想要探索那些最有意思的思路和技术,然后分享给更多的读者。

Fred:不论是通常所说的编程还是具体的Web开发都在以惊人的速度进化。我觉得本书是一个绝佳的机会来打破主流,探索新的想法并发现Web开发中的不同方式。

选择这些框架的目的并不是想比较它们,也不是为了让你在下个项目中选择它们。这本书更像是一次对Web开发中各种不同特性的框架的探索。

Q 为什么选了这 7 个框架呢 ?

Jack:我们希望能挑选出那些有着独特而强大思想的框架,而不仅仅是那些已经备受关注的框架。我们在本书中探索了极简主义、可组合、静态类型、状态机和声明式语法等。

在某些情况下,我们选择一些框架是源于我们想要探索的一些想法,而另一些则只是同类框架中最简明的例子。而且我们选择了一些互相重叠最少的框架,以确保覆盖尽可能多的思路。

Fred:在受够了那些过于复杂的所谓“企业级”框架之后,探索学习那些可以通过恰如其分的代码来进行编码的框架可谓是令人心旷神怡。

我们还设想引入客户端的框架,因为客户端的JavaScript已经不再是代码碎片的大杂烩了,这些框架给了我们编写模块化和组织良好代码的机会。

Q:你们还想引入哪些框架?

Jack:我觉得Play这个框架和Yesod旗鼓相当,它使用Scala来支持静态类型,并且还有一些其他特性。我还想将基于Elixir的框架加进来,但是目前还没有任何一个成熟的框架,因为Elixir本身也还在不停的修改中。

在另一个平行宇宙中,整本书可能都是关于前端框架的,仅仅前端就足以带来足够有意思的思想。一方面,一些非常优秀且独特的ClojureScript框架正在不断涌现,比如Webfui和Om;另一方面,Meteor和Derby也在实时和协作应用中大放异彩。

Fred:Node.js是一个本应该被包含进来的有趣的服务器端框架,但是我们更想引入一些客户端框架。当然,我们可以写一本完全使用JavaScript的书,但这并不是我们的目标。

Q 你们开始写这本书之后,有没有出现一些有趣的新框架呢?

Jack:我的RSS阅读器里存的全是关于各种新框架的文章,而且每天都会有更新。目前我打算研究的几个包括Revel(一个使用Go编写的框架)和Om(一个构建在core.async之上的ClojureScript框架)。虽然Elixir是一个很新的语言,但是基于它的Web框架已经开始不断涌现,比如Sugar和Dynamo,这些我也都要尝试一下。

Freld:新的框架不断涌现,我们都快跟不上了。由于Clojure是我最喜爱的编程语言,我想要探索的两个框架分别为total.js和Pedestal。

Q 学习这些都需要什么?

你需要Windows、MacOSX或者Linux,还有你最喜欢的浏览器。每一章都会告诉你要下载哪些工具以及对应的编程语言版本。

 

一般而言,在开发 Web 应用时,往往在一段时间之后我们会想要用另外一种方式来实现,或者使用更好的工具来实现。虽然没有完美的框架,但是探索其他框架时展开的思路,不仅可以满足应用本身的需求,而且还可以在极大程度上帮助我们使用现有工具以不同的方式来解决问题。

这本书记录了一些我们在研究开发应用程序的新思路时的一些探索。我们希望你从这个现代,而又没有经过太多探索的Web编程世界中找到乐趣。

你很可能已经有一个用来完成手头工作的框架,或者已经习惯于某个框架。你可能喜欢它,也可能讨厌它,但是你还想知道世界上有没有更好的框架。即使你并不想换一个框架或者学习一门新语言,我们认为探索一下其他开发者的好想法也会积极地影响你的工作和思维方式。

我们是对新想法和编程充满热情的终生学习者。在有如此众多的 Web 框架和编程语言的今天,非常容易就可以获得很多快乐,学习有趣而新鲜的事物,你不大可能会觉得无聊。我们在自己的职业生涯中经历了许多框架,其中一些变成了我们的新宠,另外一些则给了我们启发,还有少数则给我们本来就熟悉的领域带来了新的思路。

这本书想要带给你对 7 种截然不同的 Web 框架的感性认识,既为你展现这些框架的关键思路,又引起你的好奇心和探索精神。我们探索的每个框架都具有某些独一无二的特质。与主流框架相比,它们是更少有人走的路,而且这些路上充满了欢乐和惊喜、探索和激励。

这本书是Pragmatic Bookshelf丛书的“七周七某某”系列中的一本,这个系列还包括《七周七语言》、《七周七数据库》。本书中的每一章都讨论了一个不同的Web框架,而且大部分都是不同的编程语言,目的是为你提供一些开发现代 Web 应用程序的全新理念、风格和技术。

每一章都是独立的,并且都被组织成了3天的形式。其中我们会介绍框架,展现其独一无二的特性。章节之间并没有特别的顺序,阅读时也不需要按照特定的顺序,可以直接跳到自己感兴趣的章节开始阅读。

每个框架都因为某些独一无二的特质而被选中,当然这与它们的流行程度并没有太大关系。你可能会发现一些不论是语言本身还是框架你都没听过,但是有时候这正是那些最好的想法的藏身之所。

我们从第1章开始,介绍了Ruby世界中最为简单的框架之一Sinatra。我们在探索这个小巧而精致的框架的过程中,会创建并测试一个书签应用。

在第 2 章,我们会学习 Web 应用的新趋势:使用基于 JavaScript 的客户端框架CanJS,并使用Sinatra作为后端。我们重新实现一个书签应用,并在过程中展示可以被观察和响应的动态模型。

在第3章,我们介绍AngularJS。这是另外一个客户端的JavaScript框架,但是使用了一种完全不同的风格。AngularJS是声明式的,并且可以与你的HTML集成在一起。你只需要告诉它你想要什么,而不是如何完成。

Lisp程序员常常会说“代码即数据”,我们在第4章介绍Ring时,你会看到Web应用程序也是数据。Ring 应用运行在一个既复杂又简单的抽象层上,并从函数式编程中受益。

你之前对Web应用程序如何工作的理解将会在第5章受到挑战,这一章介绍了Webmachine,这个基于Erlang的框架将HTTP建模为一个状态机。这可以让你充分利用到这个协议的优势,而这一点恰好是其他框架所欠缺的。

第 6 章,介绍了 Yesod。通过 Haskell 的强类型、静态类型系统,避免了很多Web应用程序错误。如果你有损坏的连接或者没有很好地处理用户生成的内容,那么编译就会失败。

最后即第7章,介绍了Immutant框架,通过用Clojure包装JBoss系统,以及删除一些不必要的组件来重塑企业级 Java Web 框架。其结果就是产生一个你会欣然使用的企业级功能的组合。

在一本书中引入如此多的想法很难做到公正,于是我们不得不缩减一些你可能想要看到的功能,那些功能需要专门介绍该语言或者框架的书来覆盖。

我们假设你已经对Web应用开发比较熟悉了,我们没有解释HTML、CSS以及一些Web应用程序的基础知识。你可能之前已经做过一两个Web应用了,如果没有,也不用担心,我们假设的Web知识其实都非常基础。

我们用5个不同的编程语言介绍了7种不同的Web框架。其中有些语言你可能已经很熟悉了,比如Ruby、JavaScript,另外一些则非常奇怪。限于篇幅,本书中并没有引入语言的简介,但是我们也考虑到了第一次接触这些语言的读者。即使你之前没有接触过这些语言,也应该很容易获取框架想要表达的思路。这些思路适用于任何语言。

安装语言和框架变得越来越容易了,为了保持每一章都聚焦,我们并没有引入太多的安装或者部署的细节。大多数情况下,包管理器和构建工具会搞定这些烦琐的工作,如果你遇到了问题,请在搜索引擎中查找相关的在线文档。

我们想要在每一章中都覆盖尽可能多的内容,但是在有些情况下,我们省略了一些与正在解释的主题无关的代码,而这些代码又是正常运行应用程序所必需的。有时这些代码是由脚手架自动生成的,有时你需要自己下载代码包。每章应用里的代码都提供完整的代码包下载,请放手在下载的代码中进行修改,那样就不用什么都要从头手敲一遍了。

对于每种语言,我们都尽可能地使用了当时社区中最为流行的约定和工具。

书中的应用程序和实例都可以在“Pragmatic Programmer”网站1上找到。你还可以找到一个论坛和勘误表单,可以报告发现的问题,或者为将来的版本提一些建议。

我们希望你享受学习这7个不同的框架的探索之路,也希望这些框架中的好想法能给你更多的启发。

Jack Moffitt和Fred Daoud

2014年12月

1http://pragprog.com/book/7web/seven-web-frameworks-in-seven-weeks

 

如果只看标题,你会以为这本书只是对不同技术进行了广度优先的分析。但是令人惊讶的是它同时在深度上的展开,对每一个不同主题的核心都做了足够的强调。如果你是一个多语言狂人,或者准备成为一个,那么这本书正是写给你的。

Jim Crossley

Immutant团队核心成员,Red Hat首席软件设计师

客观且清晰!不仅仅是一个介绍,更是一个好的起点。任何一个现代程序员都需要这样的广度和深度,我强烈推荐本书。

Pablo Aguiar

软件工程咨询师

这本书非常有意思,对每个框架的介绍都快速而清晰,作者不仅快速地带你学习了每个框架,而且又令人惊奇地详细品味了每个框架的主要功能:设计哲学、实现、测试以及对进一步探索的提示。本书包含两个JavaScript框架、一个Ruby框架、一个Haskell框架、两个Clojure框架和一个Erlang框架。如果你喜欢Web开发,则一定会喜欢上这本书的。

Giles Bowkett

高级开发,知名博主

我非常喜欢读这本书。事实上,Yesod 这一章给了我很多关于如何向非 Haskell程序员介绍强类型语言的强大之处的全新想法。

Michael Snoyman

Yesod的发明者,FP Complete公司首席软件工程师

 

我们要感谢使本书得以出版的“Pragmatic Bookshelf”团队。特别感谢我们的编辑Jackie Carter,是她以自己的专业性和不懈的努力让本书变得更好,并支持到了最后。感谢Bruce Tate,我们两个都是他的书的忠实读者,我们因能追随他的脚步而感到荣幸。感谢Andy Hunt和Dave Thomas,他们创建了一个我们都感到非常兴奋的技术主题。

感谢下面这些技术审阅者,他们为每个框架都贡献了自己专业的建议:Konstantin Haase (Sinatra), David Luecke (CanJS), Miš ko Hevery (AngularJS), James Reeves (Ring), Justin Sheehy (Webmachine), Michael Snoyman (Yesod), Jim Crossley 和 Toby Crawley (Immutant)。此外,还有为多个章节都贡献了自己的评论和建议的审阅者:Kimberly Hagen、Kevin Wiley、Pablo Aguiar、Mick Thompson、Christopher Zorn、Nathaniel Schutta,以及Aaron Bedra。

如果没有框架的作者们,这些如此有创新意义的框架也就不会存在,感谢Blake Mizerany、Justin Meyer、Miš ko Hevery、Adam Abrons、Justin Sheehy、Andy Gross、Mark McGranaghan、James Reeves、Jim Crossley、Toby Crawley、Michael Snoyman,以及他们的团队和贡献者。

感谢那些在本书还在beta版本就帮助勘误的读者,他们使得本书变得更好。

Jack:我要感谢我的妻子Kim,她鼓励我编写本书,我的各种想法都先试讲给她,她还花费了很多时间来审阅本书。感谢我的两个孩子Beatrix和Jasper,他们带给了我很多欢乐。感谢Sean Johnson,他介绍了Bruce给我,而Bruce启动了整个项目。

Fred:感谢我的妻子Nadia,她在各个方面都给我以支持,生活中有她真好。感谢Lily和Ruby,他们为这个家增添了如此多的欢乐和精彩。

很多年后,我将带着叹息在一个未知的远方向人诉说:林中曾有一条两岔路,而我选择了那条更少人走的路,它改变了所有的一切。

Robert Frost

 

 

汉诺塔是一个益智游戏,里面有3个柱子和一些不同尺寸的盘子。而游戏规则是这样的:首先把所有的盘子都按照从小到大的顺序(最上面的盘子最小,最下面的盘子最大)堆放在第一个柱子上(盘子中间有一个孔,可以插在柱子上),目标就是将第一个柱子上的所有盘子都挪到第三个柱子上。挪动的过程中,不允许出现大盘子放在小盘子之上的情况。要解决这个问题本身其实并不困难,而具挑战性的是找出一个最简单的方案——使得完成该任务所需的步骤数最少。

Web框架用来解决编写Web应用的问题。使用Sinatra,不但可以非常容易并且轻巧地解决Web应用开发的问题,而且还允许你用最少的代码量来实现这一点2。举个例子,Sinatra版本的“Hello,World”就超乎想象的短小:

这里我们定义了请求类型(get),请求的URI(/hello)以及请求的结果,就这么简单!这段代码的意思是:当以HTTP的GET方式来请求/hello时,响应就是“Hello,Sinatra”。

2http://sinatrarb.com

 

Sinatra利用Ruby优雅的语法为开发Web应用定义了一套领域特定语言。诸如get,put和post这样的方法名和HTTP的请求方法一一对应。当HTTP方法和被请求的URI匹配之后,对应的方法体就会被执行,最后会返回一个HTTP响应。领域特定语言提供了一种富有表达力,同时又非常自然的方式来开发Web应用。另外,Sinatra还特别适合开发那些为客户端提供REST风格API的服务。

Sinatra 是一个非常轻量级的框架,几乎不需要依赖就可以运行。使用 Sinatra可以毫不费力地开发并启动一个Web应用。此处我们将使用一个书签应用作为示例,在这个应用中:用户可以保存并查看自己的书签,也可以标记这些书签,并且可以根据标签进行搜索。

使用Sinatra来创建REST风格的应用程序非常容易,REST风格的服务可以将你的应用程序发布成一组基于HTTP的API。有了这些后端的API,你就可以很容易地使用JavaScript的框架来进行前端的编写工作。我们将在后边的章节里讲到这一点,并会分别使用CanJS和AngularJS来进行演示。不过,不一定非要使用JavaScript框架,因为Sinatra本身就支持前端开发。

接下来我们将开始构建这个示例应用。第一天,我们将创建书签的数据模型,提供数据库持久化,并且定义REST风格的API。第二天,我们将创建HTML视图,并会使用各种不同的模板引擎。而第三天,我们会添加数据模型的校验部分,同时会加入为书签添加标记的功能,将用到Sinatra的块参数、过滤器、基于正则表达式的路由匹配等特性。

 

在第一天的学习中,我们先要配置一个可以运行的“Hello,World”程序,以确保开发环境已经配置就绪。顺便会看一下如何编写自动化测试,以确保代码可以正常运行。现在就正式开始编写示例,通过这一章的学习我们将发现 Sinatra 更多的特性。

先来看看这个可以问好的Sinatra应用吧!

首先确保你的Ruby和RubyGems已经安装好了,在命令行里输入:

我们将使用Ruby 2.0版本,不过Sinatra在Ruby 1.9下也可以很好地工作。如果上边的这些命令不能正常工作,请访问Ruby的下载页3并根据你所使用的操作系统安装相应的Ruby版本。如果你的系统中的Ruby是1.8.7,那么请注意,虽然Sinatra在Ruby 1.8.7上也可以很好地工作,但是本书的示例代码需要在Ruby 1.9及以上版本中运行。

好了,现在来安装Sinatra本身:

这就是你开发Sinatra应用所需要的所有依赖了。我们在本章的后续部分,会在需要时安装其他的gem。如果你想看到更详细的配置信息,请参考Sinatra自带的文档4

我们来创建一个文件,命名为app.rb:

然后运行它:

这里的输出告诉我们,应用程序运行在4567端口上了。这时打开浏览器,在地址栏输入http://localhost:4567/hello ,你就应该可以看到这样的一句问候语了:“Hello, Sinatra”。

看到这样的结果,就说明一切正常!不过,像这样手工来测试一个Web应用,很快就会让你非常累,而且易于出错。下面让我们来看看如何解决这个问题。

编写测试代码来保证我们应用程序的功能是非常迫切的,因为测试过程会自动地验证应用程序是否是正常工作的。我们可以在任何时刻运行这些测试,以确保我们的修改并没有破坏应用中任何部分的功能。

基于REST风格API的Web应用(比如书签),非常适合进行自动化测试。由于这种应用程序只是返回纯粹的数据,而不是可视化的页面,因此测试起来会更加容易,测试本身也会非常健壮。

RSpec是一个用来测试Web应用程序的自动化测试工具5。安装了rspec和rack-test之后,我们就可以开始了:

我们先来写一个简单的测试:以GET方式来请求/hello,然后验证返回我们预期的值和问候语。

配置了需要被测试的应用之后,我们定义了一个describe块。在RSpec中,这种块将各个测试用例组织到不同的组中,并加上了描述信息。在describe块内,我们为每个测试用例定义了it块。it块本身也有一个描述信息。这样做的原因就是,我们可以像写英语那样写测试代码:描述这个可以问好的应用程序,它会说你好。在it块中,代码会执行一些动作,并通过调用should方法来验证期望值。

使用rspec命令来运行测试:

输出中的一个点号表示一个测试已经执行成功,而底下的消息则更加详细地表明所运行过的例子没有失败。如果我们有失败的测试,比如预期“Hello, Sinatra”这个输出中有一个感叹号,那么我们会得到:

注意这次输出中没有点号了,取而代之的是一个F,表示测试失败。输出中有一些其他有用的信息,包含我们在describe和it时指定的描述信息、失败发生的行号、预期值和实际值的对比等。

编写自动化测试是验证代码如预期般执行的好方法,而Sinatra和RSpec的结合使得编写自动化测试非常方便。在本章的剩余部分,我们将会不断地编写测试来验证这个书签的应用。

我们现在就开始实现一个简单的书签应用。在这个应用中,用户可以保存自己的书签,可以标记这些书签,并且可以获取书签列表。这里我们不会让用户直接使用浏览器来保存书签,而是提供一个在线的应用程序,它允许用户在任何地方都能访问自己的书签。另外,它还为用户提供了一个集中的地方来存储自己的书签。

我们的服务会提供如下REST风格的API:

GET  /bookmarks   - 获取一个包含了所有书签的列表
GET  /bookmarks/ID  - 按照ID获取一个书签的详情
POST  /bookmarks   - 创建一个新的书签
PUT  /bookmarks/ID  - 更新一个已有的书签
DELETE /bookmarks/ID  - 删除一个书签

我们在第一个迭代中会实现对书签的增删改查(CRUD)操作。首先,我们需要完成数据的持久化部分。

我们需要一个地方来保存书签。这里我们使用SQLite数据库6,至于对象关系映射则会使用DataMapper7。这两个工具都非常小巧,并且可以很好地和Sinatra组合在一起。

先来安装需要的gems:

安装之后,我们就可以使用SQLite和DataMapper了。DataMapper会将Ruby的类转换成DataMapper中的资源,资源对应于数据库中的一张表。我们会配置DataMapper,使其指向SQLite数据库,然后定义我们的数据模型。DataMapper会负责创建表,保存数据到数据库,从数据库查找数据,并回填到数据模型中。

我们先来创建一个简单的Bookmark模型类:

使用 DataMapper,创建一个资源非常直观。这里我们声明了 Bookmark 是一个DataMapper的资源,并且为其定义了三个属性。DataMapper会将这些属性和数据库的表中的列对应起来。

在Sinatra应用中,我们需要先引入DataMapper和Bookmark类。然后使用DataMapper::setup来指定SQLite数据库,并使用DataMapper::auto_upgrade!来设置数据库中的表结构:

这里配置了DataMapper创建一个SQLite的数据库,这个数据库是当前目录下的bookmarks.db文件。

对auto_upgrade!的调用会创建数据库中的表,不过如果表已经存在的话,它就什么也不做。它还会根据模型类的变化而修改表结果,比如我们在模型中加入了新的属性,它会自动更新表结构。这样每次重启之后,之前的数据都还是存在的。对于finalize,另一个选项是auto_migrate!。如果使用这个选项,每次启动应用时都会重新创建数据库结构。如果我们需要每次重启之后都有一个干净的数据库环境,比如用来测试的环境,则可以使用这个选项。

现在我们可以编写Sinatra中的方法来提供书签功能了。首先编写获取所有书签的功能:以GET方法来请求/bookmarks,然后以JSON的格式返回所有的书签。我们使用dm-serializer这个gem将DataMapper的资源转换成JSON。

将HTTP响应内容类型设置成JSON,就可以将结果集转换成JSON了。而这里通过调用DataMapper的all方法来获取所有的书签信息。

虽然书签列表功能已经就绪,但是目前还没有可供返回的数据,因此我们需要先存入一些到数据库中。要创建一个书签,可以向/bookmarks上POST一条数据,然后调用DataMapper的create方法:

创建之后返回201状态码,以表示资源已经被创建,随之返回的是新创建的书签ID。有了这个ID,客户端就可以获取这个新创建的书签了。

如果你返回一个包含了两个元素的数组,Sinatra会自动把第一个作为状态码,把第二个作为响应内容。你还可以返回一个包含三个元素的数组,Sinatra会自动将其识别为:状态码、HTTP响应头信息、响应内容。

当然也可以只返回一个状态码或者响应内容,如果没有状态码,Sinatra会使用默认值200。但是201更加明确,表明资源已经被创建。万维网联盟(W3C)为所有的HTTP方法定义了状态码,更详细的内容8可以参考W3C的文档9

根据请求信息创建书签时,应该注意到我们使用了slice方法来过滤出需要的值:URL 和标题。这可以避免数据模型被那些不需要的数据污染,并且也是一个安全保护,以防止恶意用户在我们不知情的情况下,将数据直接绑定到数据模型上。

slice方法并不是内置的,但是可以很容易地加载到Hash类中:

这个方法接受一个白名单作为参数,只有出现在白名单中的键值才会被加入最后的结果中。

要获取一个书签,我们需要处理URI上带有ID的请求:

现在,我们的书签应用算是有了一个很好的开端。

现在我们编写一个RSpec测试来确保创建一个书签是可以正常工作的。测试的策略是,先获取一个书签的列表,并记录列表的长度;然后创建一个书签,再次获取一次列表;最后验证新的列表的长度比之前的多一个。我们要还检验POST请求的响应值。

记录上一次请求中书签列表的长度。

创建书签之后,响应体应该包含一个新创建书签的链接。

验证新的书签被创建了,预期当前的列表长度比之前的多了一个。

运行rspec app_test.rb能确保我们的应用可以正常地创建书签。

更新一个已有的书签也很简单。当得到一个PUT请求,并且这个请求带有一个书签的ID时,我们先从数据库中取出这条记录,然后更新它,最后返回状态码:

这里我们返回204,表示无内容。因为这正是一个对于PUT请求合理的响应,表示服务器没有额外的信息需要返回给客户端。

我们再来看看测试:

先创建一个新的书签,并从响应中获得ID。

使用这个新的ID来发送一次PUT请求,但是带上一个不同的标题。

根据ID请求这个书签,然后判断标题确实被更新了。

我们的增删改查操作就剩下删除了。在DataMapper中,我们通过内置的destroy方法来删除一个对象:

我们现在实现了基本的REST风格API,它可以用来增删改查书签,并且代码也非常直观。你现在应该知道为什么Sinatra对于这类应用是非常好的选择了吧?

今天,我们从Sinatra的“Hello,World”例子开始,学习了如何构建REST风格的API来管理书签;学习了如何将DataMapper和SQLite与Sinatra集成起来,将书签存入数据库;同时,还学习了如何使用RSpec来完成自动化测试。第一天的学习非常高效,通过将不同的部分组装起来,我们得到了一个清晰而强大的开发Web应用的方法。

第1天的自学

查阅

实践

3http://www.ruby-lang.org/en/downloads

4http://www.sinatrarb.com/configuration.html

5http://rspec.info

6http://www.sqlite.org

7http://www.datamapper.org

8http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

9http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

 

相关图书

TypeScript全栈开发
TypeScript全栈开发
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Vue.js全平台前端实战
Vue.js全平台前端实战
Flutter内核源码剖析
Flutter内核源码剖析
智能前端技术与实践
智能前端技术与实践
从0到1:ES6快速上手
从0到1:ES6快速上手

相关文章

相关课程