rails敏捷开发《2》.doc
《rails敏捷开发《2》.doc》由会员分享,可在线阅读,更多相关《rails敏捷开发《2》.doc(87页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、.9.2 迭代 D2 :创建基于 Ajax 的购物车Iteration D2: Creating an Ajax-Based CartAjax 允许我们通过编写在浏览器中运行的代码,来与服务器端的应用程序交互。在这里,我们希望让 Add to Cart 按钮在后台调用服务器端的 add_to_card 方法,随后服务器把关于购物车的 HTML发回浏览器,我们只要把服务器更新的 HTML 片段替换到边框里就行了。要实现这种效果,通常的做法是首先编写在浏览器中运行的 JavaScript 代码,然后编写服务器端代码与 JavaScript 交互(可能是通过 JSON 之类的技术) 。好消息是,只要
2、使用 Rails,这些东西都将被隐藏起来:我们使用 Ruby(再借助一些 Rails 辅助方法)就可以完成所有功能。向应用程序中引入 Ajax 的技巧在于“小步前进” ,所以我们先从最基本的开始:修改货品列表页,让它向服务器端应用程序发起 Ajax 请求;应用程序则应答一段 HTML 代码,其中展示了最新的购物车。在索引页上,目前我们是用 button_to()来创建“Add to Cart”链接的。揭开神秘的面纱,button_to()其实就生成了 HTML 的标记。下列辅助方法:add_to_cart, :id = product %会生成类似这样的 HTML 代码这是一个标准的 HTML
3、 表单,所以,当用户点击提交按钮时,就会生成一个 POST 请求。我们不希望这样,而是希望它发送一个 Ajax 请求。为此,必须更直接地编写表单代码可以使用form_remote_tag 这个 Rails 辅助方法。 “form_._tag”这样的名字代表它会生成 HTML 表单,“remote”则说明它会发起 Ajax 远程调用。现在,打开 app/views/store 目录下的index.html.erb 文件,将 button_to()调用替换为下列代码:depot_l/app/views/store/index.html.erb :action = add_to_cart, :id
4、= product do %用:url 参数,你就可以告诉 form_remote_tag()应该如何调用服务器端的应用程序。该参数接收一个 hash,其中的值就跟传递给 button_to()方法的参数一样。在表单内部(也就是 do 和 end 之间的代码块中),我们编写了一个简单的提交按钮。在用户看来,这个页面就跟以前一模一样。虽然现在处理的是视图,但我们还需要对应用程序做些调整,让它把 Rails 需要用到的JavaScript 库发送到用户的浏览器上。在第 24 章“Web 2.0”(第 521 页)中,我们还会详细讨论这个话题;现在,我们只需在 store 布局的部分里调用 java
5、script_include_tag 方法即可。depot_l/app/views/layouts/store.html.erbPragprog Books Online Store“all“ % 到目前为止,浏览器已经能够向我们的应用程序发送 Ajax 请求,下一步就是让应用程序做出应答。我们打算创建一段 HTML 代码来代表购物车,然后让浏览器把这段 HTM 插入当前页面的 DOM1,替换掉当.前显示的购物车。为此,我们要做的第一个修改就是不再让 add_to_cart 重定向到首页。(我们知道,我们刚刚才加上这个功能,现在又要把它拿掉了我们很敏捷,对吧?) 我们调用 respond_to
6、()方法并告诉它我们要响应的是.js 格式文件 2。Download depot_l/app/controllers/store_controller.rbdef add_to_cartproduct = Product.find(params:id)cart = find_cartcart.add_product(product) respond_to do |format| format.js endrescue ActiveRecord:RecordNotFoundlogger.error(“Attempt to access invalid product #params:id“ )r
7、edirect_to_index(“Invalid product“ )end修改的结果是,当 add_to_cart 完成对 Ajax 请求的处理之后,Rails 就会查照 add_to_cart这个模板来执行渲染。在第 118 页,我们已经删掉了旧的.html.erb 模板,看起来现在又需要把它弄回来了。不过,还是让我们换另一种方式来做这件事吧。Rails 支持 RJS 模板的概念“JS”指的是 JavaScript。.js.rjs 模板可以将 JavaScript发送到浏览器,而你需要写的只是服务器端的 Ruby 代码。下面我们就来编写第一个.rjs 模板:add_to_cart.js.
8、rjs,它和别的模板一样,也位于 app/views/store 目录下。depot_l/app/views/store/add_to_cart.js.rjspage.replace_html(“cart“ , :partial = “cart“ , :object = cart)我们来分析一下这个模板。page 这个变量是 JavaScript 生成器的实例这是 Rails 提供的一个类,它知道如何在服务器端创建 JavaScript,并使其在浏览器上运行。在这里,我们希望它找到当前页面上 id 为 cart 的元素,然后将其中的内容替换成某些东西。传递给 replace_html 的参数看
9、上去很眼熟,因为它们就跟 store 布局中渲染局部模板时传入的参数完全一样。这个简单的 RJS 模板就会渲染出用于显示购物车的 HTML 代码,随后就会告诉浏览器将 id=“cart“的中的内容替换成这段 HTML 代码。这有效吗?在书里很难演示,不过它确实有效。首先刷新首页,以确保 form_remote_tag 调用和JavaScript 库被加载到浏览器。然后,点击 Add to Cart 按钮,就应该能看到边框里的购物车信息被更新了,同时浏览器却不会有任何刷新页面的迹象。你已经创建了一个 Ajax 应用程序。排疑解难Troubleshooting虽然 Rails 极大地简化了 Aja
10、x,却没办法让它变得易如反掌。而且,由于涉及到几种技术的松散整合,一旦 Ajax 出现故障,可能会很难跟踪调试。这也是应该始终小步前进、逐渐增加 Ajax 功能的原因。如果你的 Depot 应用没有显露出任何 Ajax 魔法,这里有几个提示: 你删除旧的 add_to_cart.html.erb 文件了吗? 你记得用 javascript_include_tag 将必要的 JavaScript 库包含到 store 布局中了吗? 你的浏览器是否有什么特殊的设置,强迫它每次都重新加载整个页面?有时候浏览器会在本地缓存页1 文档对象模型(Document Object Model)。这是文档结构和
11、内容在浏览器中的内部表示,我们据此来改变显示给用户的东西。2 这条语句乍看起来有些奇怪,其实就是一个使用代码块作为参数的方法调用。代码块在第 A.9 节“代码块与迭代器”中有介绍。在第 12.1 节“分别应答”中有更详细的描述。 .面内容,这也会给测试增加困难。也许你应该首先刷新整个页面,然后再进行测试。 是否收到了任何错误报告?请察看 logs 目录中的 development.log 文件。 还是日志文件,你是否看到了针对 add_to_cart 这个 action 的请求?如果没有,就表示你的浏览器并没有发起 Ajax 请求。如果 JavaScript 库已经加载到浏览器中(用 “查看源
12、文件”功能可以看到 HTML 源代码 ),是否你的浏览器禁用了 JavaScript? 有些读者告诉我们,当他们重新启动应用程序之后,基于 Ajax 的购物车就一切正常了。 如果你使用 Internet Explorer 浏览器,它有可能正运行在所谓 quirks 模式下这是为了兼容旧版本 IE 而设计的一种运行模式,它在处理 Ajax 时有很多问题。如果在页面上设置了适当的DOCTYPE 头信息,IE 就会转入 standards 模式,这种模式能够更好地处理 Ajax 内容。我们的布局模板中使用了下列头信息:客户永不满足The Customer Is Never Satisfied我们对自
13、己的表现感到相当满意:只修改了几行代码,原来那个乏昧的 Web1.0 应用就走上了 Web 2.0 和 Ajax 的康庄大道。屏住呼吸,把客户叫到身旁。什么都不用说,我们自豪地按下了 Add to Cart 按钮,然后扭头看着她,等待着她的赞扬。可是,没有赞扬,她看上去很惊讶。 “你们把我叫过来就是为了给我看一个 bug?”她问道, “你点了按钮,却什么都没发生。 ”我们耐心地解释说,其实背后已经发生好多事情了。看看边框里的购物车,看见了吗?我们添加货品的时候,购物车里的货品数量就从 4 变成了 5。“噢, ”她这样说, “我还真没注意到。 ”如果她注意不到页面更新的话,估计顾客也注意不到。看
14、来我们还需要对用户界面做点改进。9.3 迭代 D3 :高亮显示变化Iteration D3: Highlighting Changes前面就已经提到过,javascript_include_tag 辅助方法会把几个 JavaScript 库加载到浏览器中,其中之一的 effects.js 可以给页面装饰以各种有趣的可视化效果 3。在这些可视化效果中就包括如今声名显赫的“黄渐变技巧”(Yellow fade Technique)这是一种高亮显示页面元素的技巧,通常会首先把背景变成黄色,然后再渐变到白色。图 9.2 展示了将黄渐变技巧应用到我们的购物车上的效果:最后面的那张图片是最初的购物车;用户
15、点击 Add to Cart 按钮,购物车中货品的数量变成“2”,同时货品名称所在的那行文字背景变亮;随后,背景颜色又会逐渐变回原来的样子。我们来把这样的高亮效果加到购物车上:每当购物车被更新时(不管是添加了新的货品,还是改变了现有货品的数量),就把这部分的背景变亮。这样,用户就可以更清楚地看到“有东西发生了变化” ,虽然3 effect.js 是 script.aculo.us 库的一部分。在 http:/ 这里列出了一些可视化效果,你可以看看用这个库都能做些什么。.整个页面并没有刷新。我们面临的第一个问题是:如何知道购物车中的哪种货品是最近更新的?现在,每种货品在显示时都只是一个简单的 元
16、素,我们需要找到一个办法来标记出其中最近更新的一个。为此,首先需要对Cart 模型类做些调整:让 add_product()方法返回与新加货品对应的 CartItem 对象。图 9.2 加上黄渐变效果的购物车depot_m/app/models/cart.rbdef add_product(product)current_item = items.find |item| item.product = productif current_itemcurrent_item.increment_quantityelse current_item = CartItem.new(product) ite
17、ms . 经过这三个小修改之后,最近发生变化的货品所对应的元素就会被打上id=“current_item“的标记。现在,我们只要告诉 JavaScript 对这些元素施加高亮效果就行了:在add_to_cart.js.rjs 模板中调用 visual_effect 方法。depot_m/app/views/store/add_to_cart.js.rjspage.replace_html(“cart“ , :partial = “cart“ , :object = cart)page:current_item.visual_effect :highlight,:startcolor = “#8
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- rails 敏捷 开发
限制150内