程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Ruby on Rails 2.0的新特性介紹

Ruby on Rails 2.0的新特性介紹

編輯:關於JAVA

萬眾矚目的Ruby on Rails 2.0已經發布了,Rails框架在2004年誕生以來,一直保持著相當快的版本 升級速度:2005年發布了Rails1.0版本,2006年初發布Rails1.1版本,2007年初發布Rails1.2版本,而還 沒有等到2008年,在2007年聖誕前夕的12月6日,Rails2.0已經發布。

Rails框架每個大的版本升級都給我們帶來了相當多的新功能,新驚喜。Rails1.0帶給我們完善的單元 測試和集成測試;Rails1.1帶給我們DataBase Migration和RJS;Rails1.2讓我們看到了REST的光明前景 ,那麼Rails2.0又將帶給我們什麼呢? 我粗略的翻譯了一下Rails框架作者DHH寫的Rails2.0框架介紹文 章,以下翻譯自DHH的文章,原文在:

http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done

在經過差不多一年的開發之後,Rails2.0終於發布了。這是一個棒極了的Rails版本,包括了大量堪稱 偉大的新特性,無數的bugfix和大量功能的打磨。我們花了無數的精力去打造這樣一個非常完美合理的軟 件包。

這也是Rails框架發展歷史上的一個裡程碑。我個人在Rails框架上面的開發工作已經有四年半的時間 了,並且我們現在的貢獻者也越來越多。我對這幾年我們所做出的工作和我們一直堅持的信念感到非常的 滿意。我們一直在堅持這一點並且不斷推動它。

在詳細的介紹Rails2.0之前,我要向那些為Rails框架做出過貢獻的每一個人致以深深的謝意,不論是 像一個家庭那樣其樂融融的Rails核心開發團隊,還是成千上萬的、而且年復一年為Rails提交補丁,積極 參與Rails社區人們。Rails2.0也是大規模開源軟件開發社區的一個重大勝利,而你完全可以自豪於你在 Rails社區當中扮演的角色和做出的貢獻。干杯!

現在讓我們簡單的窺一斑見全豹的看看Rails的那些閃閃發光的特性:

Action Pack: Resources

Controller裡面充斥著大量action方法的時代已經過去了,我們對REST架構的應用進行了大量的改進 和提高。首先,我們不再使用分號來隔離自定義的方法,而是采用斜線,例如原來是 /people/1;edit的 URL,現在改成了 /people/1/edit.另外我們還對URL路由資源添加了命名空間的支持,因此像後台管理的 接口你可以像這樣非常簡單的定義:

map.namespace(:admin) do |admin| 
 admin.resources :products, 
  :collection => { :inventory => :get }, 
  :member   => { :duplicate => :post }, 
  :has_many  => [ :tags, :images, :variants ] 
end

這種方式可以讓你按照如下的方式定義命名路由,例如:inventory_admin_products_url和 admin_product_tags_url等等。為了方便的記錄所有的路由規則,我們添加了一個rake任務叫做“rake routes”,它能夠列舉出來routes.rb定義的所有命名路由規則。

此外我們還引入了一個新的約定,即所有基於資源的controller默認都是復數形式的。這樣即便單個 資源在不同的路由規則中被多次引用,仍然可以指向同一個controller來處理,例如:

# /avatars/45 => AvatarsController#show 
map.resources :avatars 
 
# /people/5/avatar => AvatarsController#show  
map.resources :people, :has_one => :avatar

Action Pack: Multiview

與資源映射一起進行功能增強的還有MultiView。我們已經有了respond_to方法,但我們可以更進一步 ,把MultiView控制延伸到模板裡面去。我們現在可以根據模板文件的後綴格式來決定使用什麼render機 制。因此,show.rhtml你可以寫成show.rhtml.erb,這就表明是一個默認的rhtml模板,和你過去在 Action裡面使用respond_to聲明的format.html是一個意思。此外你還可以使用諸如show.csv.erb,它表 明顯示為csv格式的數據,並且使用默認的erb去render它。

所以,新的模板格式是: action.format.renderer。例如:

* show.erb: 不管什麼格式的顯示方式都使用默認的erb顯示show模板

* index.atom.builder: 用Builder庫來render XML文件,輸出的文件類型為RSS的AOTM類型

* edit.iphone.haml: 使用用戶自己定義的HAML render機制來輸出模板內容到iPhone手機上面

說到iPhone手機,我們可以自己造一個專用的類型來實現內部路由。當你需要類似iPhone這樣的特殊 的HTML接口的時候,我們所要做的就是:

# should go in config/initializers/mime_types.rb 
Mime.register_alias "text/html", :iphone 
 
class ApplicationController < ActionController::Base 
 before_filter :adjust_format_for_iphone 
 
 private 
  def adjust_format_for_iphone 
   if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/

(iPhone|iPod)/] 
    request.format = :iphone 
   end 
  end 
end 
 
class PostsController < ApplicationController 
 def index 
  respond_to do |format| 
   format.html  # renders index.html.erb 
   format.iphone # renders index.iphone.erb 
  end 
 end 
end

你完全可以在config/initializers/mime_types.rb裡面注冊自己的mime type類型的映射,這個文件 默認已經提供了。

Action Pack: Record identification

為了驅使你使用基於資源的映射,我們對資源映射的controller和view的URL處理進行了大量的簡化。 我們添加了大量的命名約定,讓你可以直接把model對象轉化為資源映射的路由,例如:

# person is a Person object, which by convention will  
# be mapped to person_url for lookup 
redirect_to(person) 
link_to(person.name, person) 
form_for(person)

Action Pack: HTTP Loving

如你所期望的那樣,Rails2.0的Action Pack更加貼近HTTP,並且充分利用HTTP協議,例如資源、多種 視圖,還有更多的呢。我們添加了一個模塊來處理HTTP的Basic驗證,它能夠讓授權的API輕松跨越SSL協 議,而且他是如此的簡單易用。下面是一個例子(更多的例子請參考 ActionController::HttpAuthentication):

class PostsController < ApplicationController 
 USER_NAME, PASSWORD = "dhh", "secret"  
 
 before_filter :authenticate, :except => [ :index ] 
 
 def index 
  render :text => "Everyone can see me!"  
 end 
 
 def edit 
  render :text => "I'm only accessible if you know the password"  
 end 
 
 private 
  def authenticate 
   authenticate_or_request_with_http_basic do |user_name, password|  
    user_name == USER_NAME && password == PASSWORD 
   end 
  end 
end

此外,我們也做了很多工作讓你把JavaScript和CSS文件組織到一個邏輯單元裡面去,而不需要讓浏覽 器發起多次HTTP請求,分別獲取每個JavaScript和CSS文件,以便減少HTTP請求次數。使用 javascript_include_tag(:all, :cache => true) 這個helper在生產環境下自動把 public/javascripts/目錄下面的所有js文件打包到單個public/javascripts/all.js文件裡面,但在開發 環境下,仍然保持每個文件獨立的修改。

我們還添加了一些選項讓,僅僅幾行代碼,就能夠讓浏覽器去訪問多台服務器上面的資源。如果你添 加如下設置:ActionController::Base.asset_host = “assets%d.example.com”,那麼Rails框架就會 自動的把靜態資源的請求分發到多台物理服務器上面去,例如分發到assets1.example, assets2.example.com, assets3.example.com等等。這樣浏覽器可以同時向多台服務器下載資源,增加你 的應用的訪問速度。

Action Pack: Security

能夠很簡單的創建出來安全的應用總是一件令人愉快的事情,而Rails2.0提供了大量先進的功能來達 到這一點。非常重要的是我們現在提供了一種內建的機制來處理CRSF攻擊。我們在所有的HTML表單和AJAX 請求當中包含了一個特殊的token,而請求來自於其他的應用的時候,你就可以檢測到。所有的這些選項 在新創建的Rails2.0項目當中默認就是打開的狀態,對於你升級到Rails2.0的項目要打開這一個選項也很 容易,使用ActionController::Base.protect_from_forgery就可以了,詳細的說明請看: ActionController::RequestForgeryProtection。

對於允許用戶在應用當中提交HTML代碼的情況,防止XSS攻擊現在也變得更加簡單了。 TextHelper#sanitize方法從過濾黑名單變成了驗證白名單。如果你已經使用了sanitize方法,你就會自 動獲得更好的保護。當然你也可以自行調整默認允許的HTML tag,請看TextHelper#sanitize獲取詳情。

最後,我們還添加了“HTTP only cookies”支持,這一特性並不是所有的浏覽器都支持,但是對於支 持的浏覽器你就可以派上用場了。

Action Pack: Exception handling

大多數常見的異常都可以統一處理,而不是每個需要單獨的處理。通常情況下,你只需要覆蓋 rescue_action_in_public方法,來進行統一的異常處理即可。但是你也有可能需要使用自己的case語句 來處理特定場合的異常。因此我們現在提供了一個類級別的宏叫做rescue_from,你可以使用它來聲明針 對某個特定的Action來捕獲異常,例如:

class PostsController < ApplicationController 
 rescue_from User::NotAuthorized, :with => :deny_access 
 
 protected 
  def deny_access 
   ... 
  end 
end

Action Pack: Cookie store sessions

Rails2.0默認的Session存儲機制現在是基於Cookie的方案。Session也可以不必存儲在服務器的文件 系統或者數據庫系統裡面,而是以ruby hash的格式每次作為cookie發送到客戶端浏覽器來保持。這樣做 不單單會比傳統的服務器端保存Session的方式要快一些,而且完全不需要維護。你不需要在服務器上面 運行cron job任務來清理session文件,也不必擔心因為你忘記清理session文件導致你的服務器/tmp分區 下面因為塞滿了50萬的session文件,從而讓你的服務器crash掉。

如果你能夠遵循一些最佳實踐,保持session最小化,例如只在session裡面存放user_id和flash信息 ,那麼這種session機制就會很棒。但是,如果你打算在session裡面保存核彈發射代碼的話,這一存儲機 制就不是一個好主意了。因為它們無法被加密(例如用戶偽造is_admin=true),它們很容易被用戶看到。 如果對於你的應用程序來說,這是一個必須注意的問題,那麼你就應該使用傳統的session存儲機制(但你 首先應該先做一下調查)。

Action Pack: New request profiler

在一個真實的應用當中找出性能瓶頸是一個艱難的活,但有了我們新的request profiler,工作會變 得簡單很多。request profiler跟蹤一個完整的執行腳本,報告執行結果,你可以像這樣來使用它:

$ cat login_session.rb 
get_with_redirect '/' 
say "GET / => #{path}"  
post_with_redirect '/sessions', :username => 'john', :password => 'doe' 
say "POST /sessions => #{path}"  
$ ./script/performance/request -n 10 login_session.rb

這樣你就可以得到一份非常詳盡的HTML和text格式的運行報告,每個步驟執行了多少時間,有了這個 東西,你就可以很清楚的知道怎樣優化你的應用程序了。

Action Pack: Miscellaneous

還有一個值得一提的是AtomFeedHelper。它可以讓你更容易的使用增強的builder格式來創建RSS輸出 ,例如:

# index.atom.builder: 
atom_feed do |feed| 
 feed.title("My great blog!") 
 feed.updated((@posts.first.created_at)) 
 
 for post in @posts 
  feed.entry(post) do |entry| 
   entry.title(post.title) 
   entry.content(post.body, :type => 'html') 
 
   entry.author do |author| 
    author.name("DHH") 
   end 
  end 
 end 
end

在Rails2.0裡面,我們已經進行了大量的性能優化,因此對於helper的調用開銷已經變得很小了,而 且對於簡單的命名路由,我們還使用了cache,讓它們能夠執行的更快。

最後我們把in_place_editor和autocomplete_for這兩個helper從Rails框架當中挪出去,放到了Rails 官方SVN的插件目錄下面了。

Active Record: Performance

ActiveRecord進行了無數的bug修復和少量的調整,但是仍然有一些值得一提的亮點。我們添加了一個 非常簡單的查詢緩存,它能夠在同一個請求的過程當中記錄相似的SQL調用,並且緩存查詢結果。查詢緩 存對於那些很難用:include來解決的N+1次查詢問題會非常有幫助。另外我們也徹底提高了fixtures的性 能,對於大多數常規的測試套件,性能提高了50-100%。

Active Record: Sexy migrations

現在我們有一種新的migration文件中聲明的格式。以前我們是這樣寫的:

create_table :people do |t| 
 t.column, "account_id", :integer 
 t.column, "first_name", :string, :null => false 
 t.column, "last_name",  :string, :null => false 
 t.column, "description", :text 
 t.column, "created_at", :datetime 
 t.column, "updated_at", :datetime 
end

而現在,我們可以這樣寫:

create_table :people do |t| 
 t.integer :account_id 
 t.string :first_name, :last_name, :null => false 
 t.text  :description 
 t.timestamps 
end

Active Record: Foxy fixtures

近來fixtures功能受到了很多抨擊,對於fixtures的批評主要集中在fixtures之間聲明的依賴關系上 。在fixtures裡面通過聲明id屬性來作為主鍵,從而構造fixtures之間的關聯關系是個郁悶的活。現在你 可以通過這種方式聲明和編寫fixtures:

1.# sellers.yml
2.shopify:
3. name: Shopify
4.
5.# products.yml
6.pimp_cup:
7. seller: shopify
8. name: Pimp cup

如上面所示,不再需要定義id屬性,通過id來關聯fixtures了,你現在可以直接使用fixtures的名 字來建立關聯關系。

Active Record: XML in, JSON out

ActiveRecord支持XML的序列化已經有一段時間了。在Rails2.0當中,我們還添加了XML的反序列化 功能,所以你現在可以這樣用Person.new.from_xml(“David“) 來獲取person對象。當然我們也添加了 序列化到JSON格式的功能,它和XML序列化的支持是一樣的,還可以支持關聯關系的抓取,只需要寫 person.to_json就可以了。

Active Record: Shedding some weight

為了讓ActiveRecord更加簡潔和通用,我們把acts_as_list,acts_as_tree等acts_as_xxx功能挪出 了Rails,放在了Rails官方的SVN插件裡面。如果你需要用到諸如acts_as_list的話,那麼你需要安裝這 個插件,你可以./script/plugin install acts_as_list 來安裝,安裝好以後,acts_as_list功能又回 來了,用法沒有任何區別。

更加激進一點的改動是我們把所有的商業數據庫驅動全部挪到了外部的gem包裡面。因此Rails2.0僅 僅自帶MySQL、SQLite和PostgreSQL數據庫驅動。這三個數據庫是我們更加積極測試和支持的數據庫。當 然,這並非意味著我們排斥商業數據庫,我們只是希望它們能夠在Rails發行版本之外保持自己獨立的開 發和發布計劃。對於商業數據庫來說,這其實是一件好事情,讓廠商可以在基礎版本上面添加更多的異常 和處理機制,使它們工作的更好。

所有的商業數據庫驅動現在都放在gems包裡面,符合如下命名規則:activerecord-XYZ-adapter。 所以如果你安裝了activerecord-oracle-adapter包,那麼這台機器上面所有的各種版本的Rails應用程序 都可以訪問Oracle數據庫了,你卻無需修改任何一行應用的代碼。

這種方式對於新的數據庫驅動來說在Rails社區也可以更加方便的獲得支持。只要你把數據庫驅動安 裝命名規范打包成為gem,用戶就可以安裝這個gem,立刻在Rails程序當中使用到它們了。

Active Record: with_scope with a dash of syntactic vinegar

ActiveRecord::Base.with_scope被勸阻使用以避免用戶在controoler,特別是filter裡面誤用。現 在我們鼓勵用戶僅僅在model裡面使用這種格式,這也是當初我們設計這項功能的初衷和保持一個良好實 踐的需要。當然,這僅僅只是鼓勵和勸阻,如果你在衡量得失之後,非要堅持在model之外使用 with_scope的話,你盡管可以用這種方式來調用:.send(:with_scope)。

ActionWebService out, ActiveResource in

在SOAP和REST的爭論當中,Rails選擇堅定的站在REST這一邊似乎不出人意料。如果你並沒有集成其 他異構系統需求的話,那麼我們強烈勸阻你使用SOAP。作為很自然的選擇,ActionWebService現在並不在 Rails框架的依賴當中,gem包仍然保留,但是這是一個重要的信息,建議你盡量不用它。

與此同時,我們把新的ActiveResource包從beta版本升級挪入Rails框架之內。ActiveResource很像 ActiveRecord,只不過面向的不是model,而是資源。它有和ActiveRecord非常相似的API,並且可以和基 於資源的Rails應用良好的整合。例如,ActiveResource提供了一個vanilla scaffold,你可以參考。

ActiveSupport

ActiveSupport沒有多少新東西,我們只是添加了大量新的方法,例如Array#rand可以隨機取得集合 的元素,Hash#except可以過濾掉不想要的key和其他大量的Date類型的擴展。另外單元測試增加了一個 assert_difference的便利方法。簡而言之,僅僅是bugfix和調整。

Action Mailer

Action Mailer有不少更新,除了一大堆bugfix之外,我們添加了一個選項可以注冊可選的模板渲染 機制,此外還給email的單元測試添加一套assert_emails,例如驗證郵件投遞的數量:

1.assert_emails 1 do post :signup, :name => ‘Jonathan’ end

Rails: The debugger is back

為了更好的整合調試器,我們對Rails框架整體進行了一系列的改進。我最得意之作就是調試器的斷 點功能回來了,這不僅僅只是一個類似irb dump那樣的斷點數據觀測,而是一個真正的調試器。你可以單 步前進、單步後退、列舉當前位置等等。這完全得益於ruby-debug這個gem包,所以我們推薦你安裝這個 gem包,然後Rails新的調試器就可以工作了。

如果你想使用調試器,那麼首先安裝ruby-debug這個gem包,然後把“debugger”命令寫在你的應用 程序當中,接著用-debugger或者-u參數啟動服務器,當代碼執行到debugger命令的地方,你就可以在運 行服務器的終端上面直接操縱應用了,完全不需要使用script/breakpointer或者其他的什麼東西。當然 你還可以在單元測試當中使用調試器。

Rails: Clean up your environment

在Rails2.0之前的版本,config/environment.rb當中塞滿了各種各樣的啟動配置信息和代碼。現在 你可以把這些東西分門別類的放在獨立的文件當中,然後把文件放在config/initializers目錄下面,當 Rails應用啟動的時候,它們就會被自動的加載。新的Rails2.0應用自帶了兩個這樣的例子,分別是 inflections.rb(定義你自己的單復數規則)和mime_types.rb(定義你自己的擴展類型)。我們鼓勵你把啟 動配置信息放在獨立的文件裡面,而不要去改動environment.rb文件。

Rails: Easier plugin order

現在我們開始把很多功能從Rails剝離出來放到插件裡面去了,你也許有可能有一些其他依賴這些功 能的插件。例如在你自己的acts_as_extra_cool_list插件被加載之前,需要首先加載acts_as_list插件 ,因為acts_as_extra_cool_list擴展了acts_as_list。

在Rails2.0之前,設定插件的加載次序需要你在config.plugins裡面列舉所有的插件。這種做法主 要的問題是當你僅僅需要acts_as_list插件加載次序在前,而不關心其他插件加載次序的時候,未免需要 多寫太多東西。而現在你僅僅這樣寫就可以了:config.plugins = [ :acts_as_list, :all ]。

And hundreds upon hundreds of other improvements

上面我提到的這麼多特性也僅僅只是Rails2.0的冰山一角。我們可以列舉出來成千上萬的bug修復、 功能調優、新功能的添加。許許多多的熱情的貢獻者不知疲倦的在各個細節上面改進Rails框架,但是這 些工作都是非常重要的。

我希望你能夠不介意麻煩去閱讀Rails的CHANGELOG,了解更多的Rails2.0的改進。

So how do I upgrade?

如果你希望升級到Rails2.0,那麼你應該首先升級到Rails 1.2.6版本。它對於所有在Rails2.0當中 被挪出去的功能給出了警告信息。如果你的應用程序在Rails 1.2.6上面良好的運行,並且沒有任何警告 信息,那麼你就可以升級到Rails 2.0了。當然如果你用到了Rails的分頁的話,你需要安裝 classic_pagination這個插件。如果你需要使用Oracle數據庫,那麼你需要安裝activerecord-oracle- adapter這個gem包,諸如此類等等等等。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved