佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > 在Ruby on Rails中使用AJAX的教程

在Ruby on Rails中使用AJAX的教程

熱門標(biāo)簽:語(yǔ)音系統(tǒng) 企業(yè)做大做強(qiáng) 電話運(yùn)營(yíng)中心 呼叫中心市場(chǎng)需求 Win7旗艦版 硅谷的囚徒呼叫中心 客戶服務(wù) 百度AI接口

如果沒(méi)有聽(tīng)說(shuō)過(guò) Rails,那么歡迎您外星旅行歸來(lái),近幾年大概只有那個(gè)地方?jīng)]有聽(tīng)說(shuō)過(guò) Ruby on Rails 了。Rails 最吸引人的地方是能夠很快地建立功能完備的應(yīng)用程序并運(yùn)行起來(lái)。Rails 為 Ajax 而內(nèi)置集成的 Prototype.js 庫(kù)可以輕松快速地創(chuàng)建所謂的富 Internet 應(yīng)用程序。

本文將逐步引導(dǎo)您創(chuàng)建 Rails 應(yīng)用程序。然后深入分析如何利用 Ajax 特性編寫(xiě)從服務(wù)器上讀寫(xiě)數(shù)據(jù)的 JavaScript 代碼。
從容起步 Ajax 之旅——Ajax 技術(shù)資源中心

什么是 Ajax?Ajax(Asynchronous JavaScript and XML)是一種編程技術(shù),它允許結(jié)合 XML 和 JavaScript 用于 Web 應(yīng)用程序,從而打破頁(yè)面刷新的范式,使您的用戶快速方便的與 Web 應(yīng)用程序交互。

您想了解如何構(gòu)建基于 Ajax 的應(yīng)用嗎?developerWorks 中國(guó)網(wǎng)站上有非常多的關(guān)于 Ajax 的文章、教程和技巧,通過(guò)“Ajax 技術(shù)資源中心”,您可以非??旖莸卣业侥軒椭瓿膳c Ajax 相關(guān)的應(yīng)用開(kāi)發(fā)的技術(shù)參考資源。

關(guān)于 Rails 的一點(diǎn)說(shuō)明

那么到底什么是 Rails 呢?Rails 是建立在 Ruby 編程語(yǔ)言上的一種 Web 應(yīng)用程序平臺(tái)。Ruby 存在大約有 10 年了。和 Perl 以及 Python 一樣,它也是一種開(kāi)放源碼的敏捷編程語(yǔ)言,完全支持面向?qū)ο缶幊獭?/p>

Rails 作為一種應(yīng)用程序框架,強(qiáng)調(diào)使用正確的 Web 應(yīng)用程序模式,即模型-視圖-控制器(MVC)。在這里,系統(tǒng)的模型部分通常用一組映射到數(shù)據(jù)庫(kù)表的 ActiveRecord 對(duì)象表示??刂破鞑糠质且粋€(gè) Ruby 類,其方法可以對(duì)模型執(zhí)行各種操作。視圖一般就是通過(guò) ERB 模板(ERB 是 Ruby 內(nèi)置的文本模板包)生成的超文本標(biāo)記語(yǔ)言代碼(HTML),形式上和 PHP 或 JavaServer Pages(JSP)代碼生成的 HTML 類似。視圖也可以是可擴(kuò)展標(biāo)記語(yǔ)言(XML)、文本、JavaScript 代碼、圖片或者其他東西。

用戶從 Rails Web 應(yīng)用程序請(qǐng)求頁(yè)面時(shí),URL 通過(guò)路由系統(tǒng)發(fā)送,后者將請(qǐng)求發(fā)送給控制器??刂破鲝哪P驼?qǐng)求數(shù)據(jù)并發(fā)送給視圖完成格式化。

創(chuàng)建 Rails 應(yīng)用程序時(shí),系統(tǒng)自動(dòng)生成一些目錄和基本文件。包括隨系統(tǒng)安裝的 JavaScript 文件目錄(包括 Prototype.js 庫(kù))、視圖、模型和控制器目錄,甚至還有存放從其他開(kāi)發(fā)人員那里下載的插件的目錄。


開(kāi)始使用 Rails

創(chuàng)建 Rails 應(yīng)用程序最簡(jiǎn)單的辦法就是使用一個(gè)預(yù)先打好包的 Rails 系統(tǒng)。如果平臺(tái)是 Microsoft? Windows?,建議您使用 Instant Rails。在 Macintosh 機(jī)器上我非常喜歡 Locomotive 2 應(yīng)用程序。這些應(yīng)用程序都包括 Rails 框架、Ruby 語(yǔ)言、Web 服務(wù)器和 MySQL。下載了這么多東西(確實(shí)是這樣)之后,創(chuàng)建 Rails 應(yīng)用程序僅僅是舉手之勞了。

本文將創(chuàng)建一個(gè)新的菜譜應(yīng)用程序,稱為Recipe,只需要一個(gè)表。清單 1 顯示了 Recipe 應(yīng)用程序的數(shù)據(jù)庫(kù)遷移。
清單 1. 數(shù)據(jù)庫(kù)遷移

class CreateRecipes  ActiveRecord::Migration
 def self.up
 create_table ( :recipes, :options => 'TYPE=InnoDB' ) do |t|
 t.column :name, :string, :null => false
 t.column :description, :text, :null => false
 t.column :ingredients, :text, :null => false
 t.column :instructions, :text, :null => false
 end
 end

 def self.down
 drop_table :recipes
 end
end

數(shù)據(jù)庫(kù)中只有一個(gè)表:recipes。包含五個(gè)字段:name、description、ingredients、instructions,還有一個(gè)字段是 Rails 基礎(chǔ)設(shè)施自動(dòng)維護(hù)的唯一標(biāo)識(shí)符。

建立好數(shù)據(jù)庫(kù)表之后,接下來(lái)就要為它包裝一個(gè) ActiveRecord 對(duì)象。該對(duì)象如 清單 2 所示。
清單 2. Recipe 模型

class Recipe  ActiveRecord::Base
 validates_presence_of :name
 validates_presence_of :description
 validates_presence_of :ingredients
 validates_presence_of :instructions
end

ActiveRecord 基類負(fù)責(zé)所有基本的數(shù)據(jù)庫(kù)訪問(wèn):查詢表、插入、更新和刪除記錄。這里只要為每個(gè)字段增加驗(yàn)證就夠了。我告訴 Rails 每個(gè)字段不能為空。


Ajax 表單

創(chuàng)建 Recipe 應(yīng)用程序的第一步是向數(shù)據(jù)庫(kù)中添加菜譜。首先介紹在 Rails 中創(chuàng)建基本 HTML 表單的標(biāo)準(zhǔn)方法。如 清單 3 中的 RecipesController 類所示。
清單 3. Recipes_controller.rb

class RecipesController  ApplicationController
 def add
 @recipe = Recipe.new
 if request.post?
 @recipe.name = params[:recipe][:name]
 @recipe.description = params[:recipe][:description]
 @recipe.ingredients = params[:recipe][:ingredients]
 @recipe.instructions = params[:recipe][:instructions]
 @recipe.save
 end
 end
end

只有一個(gè)方法 add,它首先創(chuàng)建一個(gè)空的 Recipe 對(duì)象。然后當(dāng)客戶機(jī)發(fā)出請(qǐng)求時(shí)添加參數(shù)并保存數(shù)據(jù)。

該頁(yè)面的 ERB 模板如 清單 4 所示。
清單 4. Add.rhml

html>
 body>
%= error_messages_for 'recipe' %>br/>
%= start_form_tag %>
table>
tr>td>Name/td>
td>%= text_field :recipe, :name %>/td>/tr>
tr>td>Description/td>
td>%= text_area :recipe, :description, :rows => 3 %>/td>/tr>
tr>td>Ingredients/td>
td>%= text_area :recipe, :ingredients, :rows => 3 %>/td>/tr>
tr>td>Instructions/td>
td>%= text_area :recipe, :instructions, :rows => 3 %>/td>/tr>
/table>
%= submit_tag 'Add' %>
%= end_form_tag %>
 /body>
/html>

頁(yè)面首先顯示 recipe 對(duì)象的錯(cuò)誤消息。如果用戶發(fā)布的數(shù)據(jù)沒(méi)有通過(guò) Recipe 模型對(duì)象的驗(yàn)證就會(huì)設(shè)置這些消息。然后依次為 form> 標(biāo)記、每個(gè)字段的 text_field 和 text_area 項(xiàng)、submit> 標(biāo)記和表單末尾。

這是非常標(biāo)準(zhǔn)的 Rails。安全可靠,可用于各種瀏覽器,清晰地映射到為客戶機(jī)創(chuàng)建的 HTML。但我需要的是 Web 2.0,就是說(shuō) Ajax。那么,該如何修改呢?

控制器端的 add() 方法徹底變了,如 清單 5 所示。
清單 5. Recipes_controller.rb

class RecipesController  ApplicationController
 def add
 end

 def add_ajax
 Recipe.create( { :name => params[:recipe][:name],
 :description => params[:recipe][:description],
 :ingredients => params[:recipe][:ingredients],
 :instructions => params[:recipe][:instructions] } )
 end
end

add() 方法不再做任何事,因?yàn)橛幸粋€(gè)新的方法 add_ajax() 處理客戶機(jī)返回的數(shù)據(jù)。

對(duì)于模板來(lái)說(shuō),不需要做大的修改,如 清單 6 所示。
清單 6. add.rhtml 的開(kāi)始部分

html>
 head>
 %= javascript_include_tag :defaults %>
 /head>
 body>
 div id="counter">/div>
%= form_remote_tag :url => { :action => 'add_ajax' },
 :complete => 'document.forms[0].reset();',
 :update => 'counter' %>
table>
tr>td>Name/td>

文件開(kāi)始在 HTML 中增加了 head 部分,其中包含對(duì) Rails 默認(rèn) JavaScript 文件的引用。這就是 Prototype.js 系統(tǒng),完成 Ajax 工作的大部分。

然后添加了 div> 標(biāo)記 counter,保存從 Ajax 請(qǐng)求返回的結(jié)果。并不是非常必要,但給用戶一些反饋也不錯(cuò)。

最后,將原來(lái)的 start_form_tag 改為 form_remote_tag。form_remote_tag 有幾個(gè)參數(shù),其中最重要的是 url,它指定向何處發(fā)送數(shù)據(jù)。第二個(gè)是一個(gè)完整的處理程序,其中的 JavaScript 代碼在 Ajax 請(qǐng)求完成時(shí)執(zhí)行。這里重置表單以便讓用戶輸入新的菜譜。然后使用 update 參數(shù)告訴 Rails 把 add_ajax 動(dòng)作的輸出發(fā)送到何處。

add_ajax() 方法還需要一個(gè)模板。如 清單 7 所示。
清單 7. Add_ajax.rhtml

%= Recipe.find(:all).length %> recipes now in database

如此而已。但并不完全是。這僅僅是從標(biāo)準(zhǔn) HTML 表單遷移到 Rails 中的 Ajax 表單。圖 1 顯示了準(zhǔn)備提交的 Ajax 表單。
圖 1. Ajax 表單

接下來(lái)是更加動(dòng)態(tài)的交互,比如使用 Ajax 動(dòng)態(tài)搜索。


Ajax 動(dòng)態(tài)搜索

Prototype.js 提供了觀察頁(yè)面上的字段和表單的功能。我利用這種功能觀察一個(gè)文本字段,可在其中輸入部分菜譜名。然后運(yùn)行 RecipesController 的搜索方法,輸出放在文本字段下方的 div> 標(biāo)記中。首先從更新的 RecipesController 開(kāi)始,如 清單 8 所示。
清單 8. Recipes_controller.rb

class RecipesController  ApplicationController
...
 def index
 end

 def search_ajax
 @recipes = Recipe.find( :all,
 :conditions => [ "name LIKE ?",
 "%#{params[:recipe][:name]}%" ] )
 render :layout=>false 
 end
end

index() 方法呈現(xiàn) HTML 表單。search_ajax() 方法根據(jù)搜索參數(shù)查找菜譜并把數(shù)據(jù)發(fā)送給 ERB 模板格式化。index.rtml 模板如 清單 9 所示。
清單 9. Index.rhtml

html>
head>
%= javascript_include_tag :defaults %>
/head>
 body>
%= form_tag nil, { :id => 'search_form' } %>
%= text_field 'recipe', 'name' %>
%= end_form_tag %>

div id="recipe">
/div>

%= observe_form :search_form, :frequency => 0.5,
 :update => 'recipe',
 :url => { :action => 'search_ajax' } %> 
 /body>
/html>

在 清單 9 的開(kāi)頭同樣包括了 JavaScript 庫(kù)。然后創(chuàng)建一個(gè)具有搜索字段和 div> 標(biāo)記的 form 表單用來(lái)保存搜索返回的數(shù)據(jù)。最后調(diào)用 observe_form() 輔助方法,它創(chuàng)建 JavaScript 代碼觀察表單的變化,并把表單數(shù)據(jù)發(fā)送到 search_ajax() 方法。然后將該方法的結(jié)果放到 recipe div> 中。

search_ajax.rhtml 表單的代碼如 清單 10 所示。
清單 10. Search_ajax.rhtml

% @recipes.each { |r| %>
h1>%= r.name %>/h1>
p>%= r.description %>/p>
% } %>

由于搜索結(jié)果可能有多項(xiàng),循環(huán)遍歷菜譜列表并輸出其名稱和說(shuō)明。

當(dāng)在瀏覽器中打開(kāi)該站點(diǎn)并在地址欄中輸入 apple 的時(shí)候,我找到了蘋(píng)果餡餅的做法,如 圖 2 所示。
圖 2. Ajax 動(dòng)態(tài)搜索

這就是最簡(jiǎn)單的實(shí)現(xiàn)。但如果希望進(jìn)一步了解蘋(píng)果餡餅該如何做?可以使用 Ajax 在需要時(shí)動(dòng)態(tài)獲得配料和做法嗎?很高興您這樣問(wèn)!當(dāng)然能!


在命令中增加內(nèi)容

有時(shí)候,讓用戶選擇下載更多的信息而不是生硬地把信息堆到頁(yè)面上更加友好。傳統(tǒng)上,Web 應(yīng)用程序開(kāi)發(fā)人員使用隱藏的 div> 標(biāo)記包含信息,當(dāng)用戶要求這些資料時(shí)再顯示出來(lái)。Rails 提供了一種更優(yōu)美的方法,可以在需要的時(shí)候使用 Ajax 請(qǐng)求數(shù)據(jù)。

清單 11 中的菜單模板增加了 link_to_remote() 輔助方法調(diào)用。
清單 11. Search_ajax.rhtml

% @recipes.each { |r| %>
h1>%= r.name %>/h1>
p>%= r.description %>/p>
div id="extra_%= r.id %>">/div>
%= link_to_remote 'Extra',
 :url => { :action => 'get_extra_ajax', :id => r.id }, 
 :update => "extra_#{r.id}" %> 
% } %>

link_to_remote() 在頁(yè)面中添加 JavaScript 代碼和包含指定文本的 anchor(a>)標(biāo)記??蛻魡螕粼撴溄訒r(shí),頁(yè)面就會(huì)發(fā)出 Ajax 請(qǐng)求來(lái)獲得新內(nèi)容并替代原來(lái)的文本。

為了獲得新的信息,必須為 RecipesController 添加一個(gè) get_extra_ajax() 方法。如 清單 12 所示。
清單 12. Recipes_controller.rb

class RecipesController  ApplicationController
 ...
 def get_extra_ajax
 @recipe = Recipe.find( params[:id] )
 render :layout=>false 
 end
end

此外還需要一個(gè)模板 get_extra_ajax.rhtml 來(lái)格式化這些信息。清單 13 顯示了該模板。
清單 13. Get_extra_ajax.rhtml

blockquote>%= simple_format @recipe.ingredients %>/blockquote>
p>%= simple_format @recipe.instructions %>/p>

現(xiàn)在回到頁(yè)面并輸入 apple,將看到 圖 3 所示的結(jié)果。
圖 3. 增加了可以訪問(wèn)配料及做法的鏈接

單擊該鏈接時(shí),瀏覽器使用 Ajax 從 Web 服務(wù)器檢索額外的資料并顯示在那個(gè)位置。結(jié)果如 圖 4 所示。
圖 4. 菜譜的細(xì)節(jié)

如果有一個(gè)行項(xiàng)或細(xì)節(jié)類型的報(bào)告,這種 Ajax 模式非常方便,因?yàn)檎?qǐng)求每個(gè)記錄的細(xì)節(jié)可能非常耗時(shí),最好在需要的時(shí)候再請(qǐng)求。此外這種技術(shù)也有助于節(jié)約屏幕資源。

可能最熱門的 Web 2.0 特性是自動(dòng)完成文本字段。否則 這趟 Ajax 之旅怎么能算完整呢?


自動(dòng)完成字段

Rails 使得構(gòu)建自動(dòng)完成字段極其簡(jiǎn)單。首先要在 index.rhtml 模板中增加一些東西。修改后的版本如 清單 14 所示。
清單 14. 修改后的 index.rhtml

html>
head>
%= javascript_include_tag :defaults %>
style>
div.auto_complete {
 width: 300px; 
 background: #fff; 
} 
div.auto_complete ul { 
 border: 1px solid #888; 
 margin: 0px; 
 padding: 0px; 
 width: 100%; 
 list-style-type: none; 
} 
div.auto_complete ul li { 
 margin: 0px; 
 padding: 3px; 
} 
div.auto_complete ul li.selected { 
 background-color: #ffb; 
} 
div.auto_complete ul strong.highlight { 
 color: #800; 
 margin: 0px; 
 padding: 0px; 
} 
/style>
/head>
 body>
%= form_tag nil, { :id => 'search_form' } %>
p>%= text_field 'recipe', 'name', :autocomplete => 'off' %>/p>
div class="auto_complete" id="recipe_name_auto_complete">/div> 
%= auto_complete_field :recipe_name,
 :url => { :action=>'autocomplete_recipe_name' },
 :tokens => ',' %>
%= end_form_tag %>
...

文件上方的級(jí)聯(lián)樣式表(CSS)部分用于自動(dòng)完成字段的下拉列表。此外還對(duì) text_field 略做修改關(guān)閉瀏覽器的自動(dòng)完成機(jī)制。下拉列表中的項(xiàng)放在新增的 div> 中,這些項(xiàng)將調(diào)用 auto_complete() 方法。auto_complete() 輔助方法創(chuàng)建客戶端 JavaScript 代碼調(diào)用服務(wù)器上的 autocomplete_recipe_name() 方法以及 recipe name 文本字段的當(dāng)前內(nèi)容。

RecipesController 的 autocomplete_recipe_name() 方法搜索該名稱,如 清單 15 所示。
清單 15. Recipes_controller.rb

class RecipesController  ApplicationController
...
 def autocomplete_recipe_name
 @recipes = Recipe.find( :all,
 :conditions => [ "name LIKE ?",
 "%#{params[:recipe][:name]}%" ] )
 render :layout=>false 
 end
end

還需要一個(gè) ERB 模板建立列表,如 清單 16 所示。
清單 16. Autocomplete_recipe_list.rb

ul class="autocomplete_list"> 
% @recipes.each { |r| %> 
li class="autocomplete_item">%= r.name %>/li> 
% } %> 
/ul>

自動(dòng)完成系統(tǒng)查找一個(gè) HTML 列表(ul>),其中每個(gè)列表項(xiàng)都是一個(gè) option。使用 index.rhtml 頁(yè)面的 CSS (或者您提供的樣式表)格式化。

為了查看自動(dòng)完成的效果,在瀏覽器中打開(kāi)頁(yè)面,然后輸入 test。我在 test 菜譜中加入了一些數(shù)據(jù)。結(jié)果如 圖 5 所示。
圖 5. 下拉自動(dòng)完成列表

可以使用上下箭頭鍵選擇一個(gè)選項(xiàng)然后按 Enter 鍵選擇。這樣將把選擇的內(nèi)容復(fù)制到文本字段中。

非常靈活,感謝 Rails 體系結(jié)構(gòu),它使這很容易實(shí)現(xiàn)。

結(jié)束語(yǔ)

無(wú)需諱言,我喜歡 Rails。從使用它的那一刻起我就被它深深吸引了。就我所見(jiàn),Web 的很多開(kāi)發(fā)人員都被它吸引了。為什么不呢?Rails 使得創(chuàng)建高交互性的 Web 應(yīng)用程序易如反掌。

即使您還沒(méi)有開(kāi)始編寫(xiě) Rails 應(yīng)用程序,我也建議您下載 Instant Rails 或 Locomotive 應(yīng)用程序開(kāi)始嘗試一下。您將體會(huì)到很多樂(lè)趣,并學(xué)習(xí)到很多可用于 Java? PHP 或 Microsoft .NET 應(yīng)用程序的東西。也許您會(huì)發(fā)現(xiàn)您希望一直編寫(xiě) Rails 代碼。

您可能感興趣的文章:
  • Windows下Ruby on Rails開(kāi)發(fā)環(huán)境安裝配置圖文教程
  • ruby on rails 代碼技巧
  • 攻克CakePHP(PHP中的Ruby On Rails框架)圖文介紹
  • 在阿里云 (aliyun) 服務(wù)器上搭建Ruby On Rails環(huán)境
  • CentOS中配置Ruby on Rails環(huán)境
  • win7安裝ruby on rails開(kāi)發(fā)環(huán)境
  • ruby on rails中Model的關(guān)聯(lián)詳解

標(biāo)簽:山西 海南 山西 崇左 喀什 濟(jì)南 安康 長(zhǎng)沙

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《在Ruby on Rails中使用AJAX的教程》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    闽侯县| 东安县| 盘锦市| 义乌市| 五常市| 财经| 泸州市| 漳浦县| 汉寿县| 永川市| 宣城市| 临清市| 秦皇岛市| 东港市| 杨浦区| 东安县| 柯坪县| 灵川县| 杭锦旗| 廊坊市| 浮山县| 汾西县| 仙游县| 百色市| 凤凰县| 民勤县| 江山市| 察哈| 沙洋县| 济源市| 治多县| 敦煌市| 夏河县| 瓮安县| 保靖县| 永康市| 扎鲁特旗| 临汾市| 银川市| 西吉县| 兴化市|