在Ruby on Rails中使用AJAX的教程_ruby專題

來源:互聯網
上載者:User

如果沒有聽說過 Rails,那麼歡迎您外星旅行歸來,近幾年大概只有那個地方沒有聽說過 Ruby on Rails 了。Rails 最迷人的地方是能夠很快地建立功能完備的應用程式並運行起來。Rails 為 Ajax 而內建整合的 Prototype.js 庫可以輕鬆快速地建立所謂的富 Internet 應用程式。

本文將逐步引導您建立 Rails 應用程式。然後深入分析如何利用 Ajax 特性編寫從伺服器上讀寫資料的 JavaScript 代碼。
從容起步 Ajax 之旅——Ajax 技術資源中心

什麼是 Ajax?Ajax(Asynchronous JavaScript and XML)是一種編程技術,它允許結合 XML 和 JavaScript 用於 Web 應用程式,從而打破頁面重新整理的範式,使您的使用者快速方便的與 Web 應用程式互動。

您想瞭解如何構建基於 Ajax 的應用嗎?developerWorks 中國網站上有非常多的關於 Ajax 的文章、教程和技巧,通過“Ajax 技術資源中心”,您可以非常快捷地找到能協助您完成與 Ajax 相關的應用開發的技術參考資源。

關於 Rails 的一點說明

那麼到底什麼是 Rails 呢?Rails 是建立在 Ruby 程式設計語言上的一種 Web 應用程式平台。Ruby 存在大約有 10 年了。和 Perl 以及 Python 一樣,它也是一種開放源碼的敏捷程式設計語言,完全支援物件導向編程。

Rails 作為一種應用程式架構,強調使用正確的 Web 應用程式模式,即模型-視圖-控制器(MVC)。在這裡,系統的模型部分通常用一組映射到資料庫表的 ActiveRecord 對象表示。控制器部分是一個 Ruby 類,其方法可以對模型執行各種操作。視圖一般就是通過 ERB 模板(ERB 是 Ruby 內建的文本模板包)產生的超文字標記語言 (HTML)代碼(HTML),形式上和 PHP 或 JavaServer Pages(JSP)代碼產生的 HTML 類似。視圖也可以是可延伸標記語言 (XML)(XML)、文本、JavaScript 代碼、圖片或者其他東西。

使用者從 Rails Web 應用程式請求頁面時,URL 通過路由系統發送,後者將請求發送給控制器。控制器從模型請求資料並發送給視圖完成格式化。

建立 Rails 應用程式時,系統自動產生一些目錄和基本檔案。包括隨系統安裝的 JavaScript 檔案目錄(包括 Prototype.js 庫)、視圖、模型和控制器目錄,甚至還有存放從其他開發人員那裡下載的外掛程式的目錄。


開始使用 Rails

建立 Rails 應用程式最簡單的辦法就是使用一個預先打好包的 Rails 系統。如果平台是 Microsoft? Windows?,建議您使用 Instant Rails。在 Macintosh 機器上我非常喜歡 Locomotive 2 應用程式。這些應用程式都包括 Rails 架構、Ruby 語言、Web 服務器和 MySQL。下載了這麼多東西(確實是這樣)之後,建立 Rails 應用程式僅僅是舉手之勞了。

本文將建立一個新的菜譜應用程式,稱為Recipe,只需要一個表。清單 1 顯示了 Recipe 應用程式的資料庫遷移。
清單 1. 資料庫遷移

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 endend

資料庫中只有一個表:recipes。包含五個欄位:name、description、ingredients、instructions,還有一個欄位是 Rails 基礎設施自動維護的唯一識別碼。

建立好資料庫表之後,接下來就要為它封裝一個 ActiveRecord 對象。該對象如 清單 2 所示。
清單 2. Recipe 模型

class Recipe < ActiveRecord::Base validates_presence_of :name validates_presence_of :description validates_presence_of :ingredients validates_presence_of :instructionsend

ActiveRecord 基類負責所有基本的資料庫訪問:查詢表、插入、更新和刪除記錄。這裡只要為每個欄位增加驗證就夠了。我告訴 Rails 每個欄位不可為空。


Ajax 表單

建立 Recipe 應用程式的第一步是向資料庫中添加菜譜。首先介紹在 Rails 中建立基本 HTML 表單的標準方法。如 清單 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 endend

只有一個方法 add,它首先建立一個空的 Recipe 對象。然後當客戶機發出請求時添加參數並儲存資料。

該頁面的 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>

頁面首先顯示 recipe 對象的錯誤訊息。如果使用者發布的資料沒有通過 Recipe 模型對象的驗證就會設定這些訊息。然後依次為 <form> 標記、每個欄位的 text_field 和 text_area 項、<submit> 標記和表單末尾。

這是非常標準的 Rails。安全可靠,可用於各種瀏覽器,清晰地映射到為客戶機建立的 HTML。但我需要的是 Web 2.0,就是說 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] } ) endend

add() 方法不再做任何事,因為有一個新的方法 add_ajax() 處理客戶機返回的資料。

對於模板來說,不需要做大的修改,如 清單 6 所示。
清單 6. add.rhtml 的開始部分

<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>

檔案開始在 HTML 中增加了 head 部分,其中包含對 Rails 預設 JavaScript 檔案的引用。這就是 Prototype.js 系統,完成 Ajax 工作的大部分。

然後添加了 <div> 標記 counter,儲存從 Ajax 請求返回的結果。並不是非常必要,但給使用者一些反饋也不錯。

最後,將原來的 start_form_tag 改為 form_remote_tag。form_remote_tag 有幾個參數,其中最重要的是 url,它指定向何處發送資料。第二個是一個完整的處理常式,其中的 JavaScript 代碼在 Ajax 請求完成時執行。這裡重設表單以便讓使用者輸入新的菜譜。然後使用 update 參數告訴 Rails 把 add_ajax 動作的輸出發送到何處。

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

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

如此而已。但並不完全是。這僅僅是從標準 HTML 表單遷移到 Rails 中的 Ajax 表單。圖 1 顯示了準備提交的 Ajax 表單。
圖 1. Ajax 表單

接下來是更加動態互動,比如使用 Ajax 動態搜尋。


Ajax 動態搜尋

Prototype.js 提供了觀察頁面上的欄位和表單的功能。我利用這種功能觀察一個文字欄位,可在其中輸入部分菜譜名。然後運行 RecipesController 的搜尋方法,輸出放在文字欄位下方的 <div> 標記中。首先從更新的 RecipesController 開始,如 清單 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  endend

index() 方法呈現 HTML 表單。search_ajax() 方法根據搜尋參數尋找菜譜並把資料發送給 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 的開頭同樣包括了 JavaScript 庫。然後建立一個具有搜尋欄位和 <div> 標記的 form 表單用來儲存搜尋返回的資料。最後調用 observe_form() 輔助方法,它建立 JavaScript 代碼觀察表單的變化,並把表單資料發送到 search_ajax() 方法。然後將該方法的結果放到 recipe <div> 中。

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

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

由於搜尋結果可能有多項,迴圈遍曆菜譜列表並輸出其名稱和說明。

當在瀏覽器中開啟該網站並在地址欄中輸入 apple 的時候,我找到了蘋果餡餅的做法,如 圖 2 所示。
圖 2. Ajax 動態搜尋

這就是最簡單的實現。但如果希望進一步瞭解蘋果餡餅該如何做?可以使用 Ajax 在需要時動態獲得配料和做法嗎?很高興您這樣問!當然能!


在命令中增加內容

有時候,讓使用者選擇下載更多的資訊而不是生硬地把資訊堆到頁面上更加友好。傳統上,Web 應用程式開發人員使用隱藏的 <div> 標記包含資訊,當使用者要求這些資料時再顯示出來。Rails 提供了一種更優美的方法,可以在需要的時候使用 Ajax 請求資料。

清單 11 中的菜單模板增加了 link_to_remote() 輔助方法調用。
清單 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() 在頁面中添加 JavaScript 代碼和包含指定文本的 anchor(<a>)標記。客戶單擊該連結時,頁面就會發出 Ajax 請求來獲得新內容並替代原來的文本。

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

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

此外還需要一個模板 get_extra_ajax.rhtml 來格式化這些資訊。清單 13 顯示了該模板。
清單 13. Get_extra_ajax.rhtml

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

現在回到頁面並輸入 apple,將看到 圖 3 所示的結果。
圖 3. 增加了可以訪問配料及做法的連結

單擊該連結時,瀏覽器使用 Ajax 從 Web 服務器檢索額外的資料並顯示在那個位置。結果如 圖 4 所示。
圖 4. 菜譜的細節

如果有一個行項或細節類型的報告,這種 Ajax 模式非常方便,因為請求每個記錄的細節可能非常耗時,最好在需要的時候再請求。此外這種技術也有助於節約螢幕資源。

可能最熱門的 Web 2.0 特性是自動完成文字欄位。否則 這趟 Ajax 之旅怎麼能算完整呢?


自動完成欄位

Rails 使得構建自動完成欄位極其簡單。首先要在 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 %>...

檔案上方的階層式樣式表(CSS)部分用於自動完成欄位的下拉式清單。此外還對 text_field 略做修改關閉瀏覽器的自動完成機制。下拉式清單中的項放在新增的 <div> 中,這些項將調用 auto_complete() 方法。auto_complete() 輔助方法建立用戶端 JavaScript 代碼調用伺服器上的 autocomplete_recipe_name() 方法以及 recipe name 文字欄位的當前內容。

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  endend

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

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

自動完成系統尋找一個 HTML 列表(<ul>),其中每個清單項目都是一個 option。使用 index.rhtml 頁面的 CSS (或者您提供的樣式表)格式化。

為了查看自動完成的效果,在瀏覽器中開啟頁面,然後輸入 test。我在 test 菜譜中加入了一些資料。結果如 圖 5 所示。
圖 5. 下拉自動完成列表

可以使用上下方向鍵選擇一個選項然後按 Enter 鍵選擇。這樣將把選擇的內容複寫到文字欄位中。

非常靈活,感謝 Rails 體繫結構,它使這很容易實現。

結束語

無需諱言,我喜歡 Rails。從使用它的那一刻起我就被它深深吸引了。就我所見,Web 的很多開發人員都被它吸引了。為什麼不呢?Rails 使得建立高互動性的 Web 應用程式易如反掌。

即使您還沒有開始編寫 Rails 應用程式,我也建議您下載 Instant Rails 或 Locomotive 應用程式開始嘗試一下。您將體會到很多樂趣,並學習到很多可用於 Java? PHP 或 Microsoft .NET 應用程式的東西。也許您會發現您希望一直編寫 Rails 代碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.