大改動(dòng)小變化 Ruby On Rails 3蓄勢(shì)待發(fā)
在過去的兩年中,Ruby on Rails應(yīng)用程序框架已經(jīng)具備了一個(gè)由托管和服務(wù)提供商組成的一體式行業(yè)、一套功能廣泛且令人印象深刻的開發(fā)工具,還有各種在Ruby 用語里稱為gems和plug-ins的補(bǔ)充庫(kù) — 可增強(qiáng)軟件的功能。
自 2007年以來,Rails 社區(qū)也已不斷壯大。全球有眾多的Rails開發(fā)人員充滿活力、團(tuán)結(jié)互助,并且渴望不斷地改進(jìn)該軟件??梢院敛豢鋸埖卣f,Rails 的改進(jìn)應(yīng)歸功于社區(qū),因?yàn)槭浅绦騿T之間不斷的相互超越使得構(gòu)建出的軟件越來越完善。如此不斷地循環(huán),各個(gè)功能才得以從初期階段快速發(fā)展,逐漸變的實(shí)用、功能不斷強(qiáng)大并完善,最終成為不可或缺的工具。
在很多情況下,社區(qū)認(rèn)為最基本的 gems 和 plug-ins 都會(huì)保留到 Rails 核心中。Rails 的 named scopes(一個(gè)查詢快捷方式),可實(shí)現(xiàn)與 nested forms 相同的功能。這是一個(gè)新增的功能,可取代以前的嘗試,并在相同的 HTML 表單中創(chuàng)建和編輯多個(gè)模型。實(shí)際上,對(duì)于 Rails 開發(fā)人員來說最困難的任務(wù)或許就是跟上變化的節(jié)奏。
Rails下一個(gè)主要的發(fā)布是Rails版本3,該版本繼續(xù)保持工具包的快速改進(jìn)。與以往相同,該軟件仍然非常 “固執(zhí)”,即仍然偏向于約定優(yōu)于配置。Rails 的核心組件始終存在,即 RESTful 路徑、關(guān)系、驗(yàn)證、模板和數(shù)據(jù)庫(kù)抽象化。不過,這些組件的許多內(nèi)部?jī)?nèi)容已經(jīng)被重寫或者進(jìn)行了改進(jìn)。最明顯的并且很大程度上借用了 Merb 的理念的就是很多 Rails 的基本功能不再密切結(jié)合。
例如,以前只對(duì) Rails 應(yīng)用程序可用的數(shù)據(jù)驗(yàn)證便捷功能現(xiàn)在成為獨(dú)立的組件,并且可以包含在 Vanilla Ruby 代碼中。如呈現(xiàn)部件和模板等控制器功能,現(xiàn)在也是相互獨(dú)立的,并且可以嵌入到任一庫(kù)中。
大改動(dòng)、小變化
Rails 3中變動(dòng)的數(shù)量太多,無法在此全部列出。此處,僅介紹一些很可能會(huì)影響到開發(fā)人員的一些變動(dòng):
Ruby On Rails 3發(fā)布說明:http://edgeguides.rubyonrails.org/3_0_release_notes.html
◆一條命令可以控制所有事件。有了 Rails 3,無需在每一個(gè)應(yīng)用程序中使用整套腳本(script/server、script/generate 以及其他),使用一條命令即可取代其功能,該命令恰如其分地被命名為 rails。例如,在以前需要鍵入 ./script/console 的地方,您現(xiàn)在只需鍵入 rails console。rails 命令還可以像以前一樣生成新的應(yīng)用程序。其運(yùn)行方式依據(jù)其是否在現(xiàn)有的 Rails 應(yīng)用程序中啟動(dòng)而有所不同。
◆可為依賴性提供具體的解決方案。協(xié)調(diào)和解決 gem 依賴性是個(gè)棘手的問題。與可用 gems 的集合一樣,gem 的修訂也是隨系統(tǒng)的不同而有所變化。因?yàn)榫哂羞@樣的多樣化,所以很難廣泛地部署或共享一個(gè) Rails 應(yīng)用程序。Rails 3 引入了 Bundler,這是一個(gè)專門用于管理依賴性的實(shí)用程序(因此無需再使用 config.gem)。您可以在應(yīng)用程序根目錄內(nèi)一個(gè)名為 Gemfile 的目錄中聲明依賴性。Bundler 將下載和存儲(chǔ)所有指定的 gem。您甚至可以在應(yīng)用程序中 “打包” gem ,以便阻止從外部存儲(chǔ)庫(kù)下載。
◆不帶查詢語句的查詢功能。一直以來,Rails 已經(jīng)可以充分運(yùn)用特定于領(lǐng)域的語言 (DSL) — 考慮一下 has_one 或 validates_numericality_of — 有一個(gè)明顯的例外:數(shù)據(jù)庫(kù)查詢??梢源_定地說,Rails 的動(dòng)態(tài)搜尋器便捷、易用,但混合使用選項(xiàng)哈希值如 :conditions、:order 和 :limit 非常常見,因?yàn)槎际?find_by_sql 語句。Rails 3 合并了 relational algebra,這是專門設(shè)計(jì)用于表示查詢的 DSL。基本命令包括 project(用于選擇列)、where(用于表示條件)、join(用于指定關(guān)系)、take 和 skip(分別用于限定和抵消),以及 group(用于聚集)等其他屬性。
用于模糊樣板代碼的控制器。Rails控制器的核心操作—new、create、edit和update—通常不變,尤其是當(dāng)控制器大部分用于CRUD操作時(shí)。事實(shí)上,控制器生成器的輸出 ./script/generate controller一般不需要進(jìn)一步的修改就可以滿足需要??紤]到這些相似性,Rails 3引入了Responder來進(jìn)一步簡(jiǎn)化代碼。例如下面是create操作全部所需的幾行代碼:
- class PostsController
- respond_to :html, :xml
- def create
- @post = Post.create(params[:post])
- respond_with(@post)
- end
- end
在該代碼片段中,如果@post保存成功,respond_with(@post) 將發(fā)送到show以顯示新的記錄,而假設(shè)對(duì)象的驗(yàn)證失敗,則發(fā)送到new。這僅僅是一個(gè)小樣本。您可以在下一章節(jié)找到這些新功能的示例以及更多內(nèi)容,例如從頭構(gòu)建Rails 3應(yīng)用程序。
#p#
***構(gòu)建 Rails 3應(yīng)用程序
要運(yùn)行 Rails 3,您的系統(tǒng)必須安裝有Ruby 1.8.7版或 Ruby 1.9.2 版,或者該編程語言的較新版本及其附加庫(kù)和解釋程序。您的機(jī)器上***同時(shí)安裝有 Git 軟件版本控制系統(tǒng),因?yàn)?Rails 3 和許多其他重要的 Rails 項(xiàng)目都是在 Git 中進(jìn)行維護(hù)的。您的系統(tǒng)還需要數(shù)據(jù)庫(kù)引擎,例如 SQLite(版本 3)、MySQL 或者 PostgreSQL。開發(fā) Rails 應(yīng)用程序時(shí),Web 服務(wù)器不是必須的,但它通常是生產(chǎn)部署的一部分。
要?jiǎng)?chuàng)建 Rails 3 應(yīng)用程序,您必須擁有Rails 3預(yù)發(fā)布gem和所有其相關(guān)產(chǎn)品。這時(shí),您只需通過運(yùn)行幾條命令(請(qǐng)參閱 清單 1)即可安裝所需的組件。(在您繼續(xù)進(jìn)行之前請(qǐng)查看 Rails 3 文檔,因?yàn)楦鶕?jù)版本的不同具體的操作會(huì)有所不同。)
- 清單 1. Rails 3 預(yù)發(fā)布 gem 和相關(guān)產(chǎn)品
- $ gem install rails3b
- Due to a rubygems bug, you must uninstall all older versions of bundler for 0.9 to work
- Successfully installed mime-types-1.16
- Successfully installed mail-2.1.2
- Successfully installed text-hyphen-1.0.0
- Successfully installed text-format-1.0.0
- Successfully installed memcache-client-1.7.8
- Successfully installed rack-1.1.0
- Successfully installed rack-mount-0.4.7
- Successfully installed abstract-1.0.0
- Successfully installed erubis-2.6.5
- Successfully installed i18n-0.3.3
- Successfully installed tzinfo-0.3.16
- Successfully installed bundler-0.9.5
- Successfully installed thor-0.13.1
- Successfully installed rails3b-3.0.1
- 14 gems installed
- $ gem install arel --pre
- Successfully installed activesupport-3.0.0.beta
- Successfully installed arel-0.2.pre
- 2 gems installed
- $ gem install rails --pre
- Successfully installed activemodel-3.0.0.beta
- Successfully installed actionpack-3.0.0.beta
- Successfully installed activerecord-3.0.0.beta
- Successfully installed activeresource-3.0.0.beta
- Successfully installed actionmailer-3.0.0.beta
- Successfully installed railties-3.0.0.beta
- Successfully installed rails-3.0.0.beta
- 7 gems installed
下一步是生成應(yīng)用程序 — 在 清單 2 中顯示了一個(gè)小 wiki。該應(yīng)用程序創(chuàng)建并管理文章。每一篇文章都有一個(gè)標(biāo)題和一些散文,通過從現(xiàn)有頁(yè)面的正文創(chuàng)建一個(gè)指向新文章的引用,您即可創(chuàng)建一篇新的文章。引用可以是任一駝峰式大小寫單詞,例如 TheSolarSystem 或者 TheOscars。
注意:可通過下面的 下載 表格獲取該 wiki 應(yīng)用程序的源代碼。
- 清單 2. Wiki Rails 應(yīng)用程序
- $ rails wiki
如果您運(yùn)行了 ls -lR 來查看應(yīng)用程序的內(nèi)容,將會(huì)顯示一些新文件:
◆Gemfile,即前面曾提到的 gem 清單。該文件必須至少包含兩行:一行指向 Rails 3 beta gem 的源,另一行則綁定 Rails 3 beta gem 本身。您或許還需要第三行(至少)以連接數(shù)據(jù)庫(kù):
- source 'http://gemcutter.org'
- gem "rails", "3.0.0.beta"
- gem "sqlite3-ruby", :require => "sqlite3"
◆config/application.rb,它包含 config/environment.rb 中以前提供的很多選項(xiàng)。雖然后者仍然保留,但很大程度上已不再使用該文件。config/application.rb 的一個(gè)顯著的附加功能是 generators block:
- config.generators do |g|
- g.orm :active_record
- g.template_engine :erb
- g.test_framework :test_unit, :fixture => true
- end
您的 Rails 3 應(yīng)用程序可以使用一些兼容的對(duì)象關(guān)系映射器 (ORM)、模板引擎和測(cè)試框架。生成器塊會(huì)指定應(yīng)用程序的***項(xiàng),并根據(jù)您的模型、視圖等調(diào)用適當(dāng)?shù)纳善鳌?/p>
◆db/seeds.rb,該文件對(duì)于 Rails 3 來說并不是新增的,但卻有必要著重介紹一下,因?yàn)樗亲罱痪脛傇黾拥墓δ埽ㄔ?Rails 2.3.4 版引入的)。如果您的應(yīng)用程序需要初始數(shù)據(jù)以正常運(yùn)行,例如一個(gè)管理用戶、價(jià)格代碼或靜態(tài)頁(yè)面,那么您可以在 db/seeds.rb 中創(chuàng)建這些數(shù)據(jù)并運(yùn)行任務(wù) rake db:seed。在 Seed 文件之前,不存在初始化的慣例,許多開發(fā)人員把代碼放入遷移中,這樣容易混淆創(chuàng)建數(shù)據(jù)庫(kù)和填充數(shù)據(jù)庫(kù)之間的不同之處。
◆config.ru,存在于每個(gè) Rails 3 應(yīng)用程序的根目錄下,即所謂的 rackup 文件,也就是基于 Rack 的應(yīng)用程序的配置文件。Rails 3 是一個(gè) Rack 應(yīng)用程序,并且與任一支持 Rack 的 Web 服務(wù)器相兼容。總的來說,除非您想要添加其他 Rack 組件,否則請(qǐng)不要更改 config.ru 文件。
還有一些其他新文件;不過大多數(shù)看上去與 Rails 版本 2.3 相似。config/routes.rb 文件的功能與以往相同,只不過更加簡(jiǎn)化、更具有 Ruby 的特色。您將很快會(huì)看到一個(gè)示例。
生成應(yīng)用程序并編輯 Gemfile 以聲明依賴性之后,下一步就是收集應(yīng)用程序所需的 gem。這是由新的實(shí)用程序 bundle(請(qǐng)參閱 清單 3)來完成的工作。
- 清單 3. 收集所需的gem
- $ bundle
- installFetching source index from http://gemcutter.org
- Resolving dependencies
- Installing abstract (1.0.0) from system gems
- Installing actionmailer (3.0.0.beta) from system gems
- Installing actionpack (3.0.0.beta) from system gems
- Installing activemodel (3.0.0.beta) from system gems
- Installing activerecord (3.0.0.beta) from system gems
- Installing activeresource (3.0.0.beta) from system gems
- Installing activesupport (3.0.0.beta) from system gems
- Installing arel (0.2.1) from rubygems repository at http://gemcutter.org
- Installing builder (2.1.2) from system gems
- Installing bundler (0.9.7) from rubygems repository at http://gemcutter.org
- Installing erubis (2.6.5) from system gems
- Installing i18n (0.3.3) from system gems
- Installing mail (2.1.2) from system gems
- Installing memcache-client (1.7.8) from system gems
- Installing mime-types (1.16) from system gems
- Installing rack (1.1.0) from system gems
- Installing rack-mount (0.4.7) from system gems
- Installing rack-test (0.5.3) from system gems
- Installing rails (3.0.0.beta) from system gems
- Installing railties (3.0.0.beta) from system gems
- Installing rake (0.8.7) from system gems
- Installing sqlite3-ruby (1.2.5) from rubygems repository at
- http://gemcutter.org with native extensions
- Installing text-format (1.0.0) from system gems
- Installing text-hyphen (1.0.0) from system gems
- Installing thor (0.13.3) from rubygems repository at http://gemcutter.org
- Installing tzinfo (0.3.16) from system gems
- Your bundle is complete!
該bundle實(shí)用程序,簡(jiǎn)稱 Bundler,可用于下載和安裝所有在 Gemfile 中指定的 gem 以及任何這些 gems 的依賴項(xiàng)(請(qǐng)參閱 清單 4)。該 bundle 實(shí)用程序還可以將所有依賴項(xiàng)復(fù)制到您的應(yīng)用程序中,使得您的代碼庫(kù)自給自足。具體來說,如果您運(yùn)行 bundle pack,Bundler 會(huì)將所有 gem 的資料復(fù)制到 vendor/cache。
- 清單 4. 運(yùn)行 bundle 實(shí)用程序
- $ bundle pack
- Copying .gem files into vendor/cache
- * bundler-0.9.7.gem
- * thor-0.13.3.gem
- * abstract-1.0.0.gem
- * mime-types-1.16.gem
- * text-hyphen-1.0.0.gem
- * rack-mount-0.4.7.gem
- * rake-0.8.7.gem
- * text-format-1.0.0.gem
- * tzinfo-0.3.16.gem
- * rack-test-0.5.3.gem
- * builder-2.1.2.gem
- * erubis-2.6.5.gem
- * memcache-client-1.7.8.gem
- * rack-1.1.0.gem
- * sqlite3-ruby-1.2.5.gem
- * i18n-0.3.3.gem
- * activesupport-3.0.0.beta.gem
- * arel-0.2.1.gem
- * mail-2.1.2.gem
- * activemodel-3.0.0.beta.gem
- * activerecord-3.0.0.beta.gem
- * actionpack-3.0.0.beta.gem
- * railties-3.0.0.beta.gem
- * actionmailer-3.0.0.beta.gem
- * activeresource-3.0.0.beta.gem
- * rails-3.0.0.beta.gem
- $ ls vendor/cache
- abstract-1.0.0.gem memcache-client-1.7.8.gem
- actionmailer-3.0.0.beta.gem mime-types-1.16.gem
- actionpack-3.0.0.beta.gem rack-1.1.0.gem
- activemodel-3.0.0.beta.gem rack-mount-0.4.7.gem
- activerecord-3.0.0.beta.gem rack-test-0.5.3.gem
- activeresource-3.0.0.beta.gem rails-3.0.0.beta.gem
- activesupport-3.0.0.beta.gem railties-3.0.0.beta.gem
- arel-0.2.1.gem rake-0.8.7.gem
- builder-2.1.2.gem sqlite3-ruby-1.2.5.gem
- bundler-0.9.7.gem text-format-1.0.0.gem
- erubis-2.6.5.gem text-hyphen-1.0.0.gem
- i18n-0.3.3.gem thor-0.13.3.gem
- mail-2.1.2.gem tzinfo-0.3.16.gem
將vendor/cache視為應(yīng)用程序自己的gem存儲(chǔ)庫(kù)。您可以將代碼庫(kù)移動(dòng)到任何地方,并可以獲得您所需的gem軟件和版本 — 無需遠(yuǎn)程存儲(chǔ)器即可實(shí)現(xiàn)。例如,如果您在 bundle pack之后運(yùn)行bundle install,gem會(huì)從您的應(yīng)用程序存儲(chǔ)庫(kù)安裝到您的系統(tǒng)中(請(qǐng)參閱 清單 5)。
- 清單 5. 安裝 gem
- Fetching source index from http://gemcutter.org
- Resolving dependencies
- Installing abstract (1.0.0) from .gem files at
- /Users/strike/projects/rails3/wiki/vendor/cache
- Installing actionmailer (3.0.0.beta) from .gem files at
- /Users/strike/projects/rails3/wiki/vendor/cache
- Installing actionpack (3.0.0.beta) from .gem files at
- /Users/strike/projects/rails3/wiki/vendor/cache
- ...
- Installing thor (0.13.3) from .gem files at
- /Users/strike/projects/rails3/wiki/vendor/cache
- Installing tzinfo (0.3.16) from .gem files at
- /Users/strike/projects/rails3/wiki/vendor/cache
- Your bundle is complete!
#p#
使用wiki
要?jiǎng)?chuàng)建應(yīng)用程序,則需要為頁(yè)面生成一個(gè)工作框架(scaffold)、創(chuàng)建數(shù)據(jù)庫(kù)、將初始頁(yè)面放到數(shù)據(jù)庫(kù)并且設(shè)定所需的路徑(請(qǐng)參閱 清單 6)。為了簡(jiǎn)單化,僅限在某些字段使用 wiki 頁(yè)面記錄:標(biāo)題、標(biāo)頭(標(biāo)題的縮略語)、正文和時(shí)間截(以用于記錄頁(yè)面的創(chuàng)建時(shí)間和***修改時(shí)間)。標(biāo)題和標(biāo)頭是字符串字段;散文是文本字段;時(shí)間截是日期和時(shí)間字段。(當(dāng)然,一個(gè)真正的 wiki 還會(huì)有其他字段,如最近的作者以及頁(yè)面的修訂歷史記錄。為了盡量簡(jiǎn)潔,該例子還省略了用戶和會(huì)話、格式以及各種身份驗(yàn)證和授權(quán)。)您可以使用 rails generate scaffold 命令生成一個(gè)初始模型、一系列視圖以及一個(gè)控制器。
- 清單 6. 完整的 wiki 應(yīng)用程序
- $ rails generate scaffold page title:string slug:string body:text --timestamps
- invoke active_record
- create db/migrate/20100221115613_create_pages.rb
- create app/models/page.rb
- invoke test_unit
- create test/unit/page_test.rb
- create test/fixtures/pages.yml
- route resources :pages
- invoke scaffold_controller
- create app/controllers/pages_controller.rb
- invoke erb
- create app/views/pages
- create app/views/pages/index.html.erb
- create app/views/pages/edit.html.erb
- create app/views/pages/show.html.erb
- create app/views/pages/new.html.erb
- create app/views/pages/_form.html.erb
- create app/views/layouts/pages.html.erb
- invoke test_unit
- create test/functional/pages_controller_test.rb
- invoke helper
- create app/helpers/pages_helper.rb
- invoke test_unit
- create test/unit/helpers/pages_helper_test.rb
- invoke stylesheets
- create public/stylesheets/scaffold.css
如果您想知道 ./script/generate 命令有何變化,回憶一下,該命令已經(jīng)被全能的 rails 命令包含了。運(yùn)行rake db:create db:migrate 以創(chuàng)建數(shù)據(jù)庫(kù):
- $ rake db:create db:migrate
- == CreatePages: migrating ====================================================
- -- create_table(:pages)
- -> 0.0010s
- == CreatePages: migrated (0.0011s) ===========================================
該Wiki現(xiàn)已存在,但卻是空的。添加一個(gè)初始頁(yè)面作為所有其他頁(yè)面的基準(zhǔn)。編輯文件 db/seeds.rb,并編寫代碼以創(chuàng)建一個(gè)新的頁(yè)面,如 清單 7 中所示:
- 清單 7. wiki 基準(zhǔn)頁(yè)面
- Page.create(
- :title => 'The Marx Brothers Wiki',
- :slug => 'Home',
- :body => 'An encyclopedic guide to the Marx Brothers.')
運(yùn)行 rake db:seed 以執(zhí)行代碼。您可以通過使用 rails console 快速瀏覽以驗(yàn)證頁(yè)面,如 清單 8 中所示。
- 清單 8. 驗(yàn)證基準(zhǔn)頁(yè)面
- $ rake db:seed
- (in /Users/strike/projects/rails3/wiki)
- $ rails console
- Loading development environment (Rails 3.0.0.beta)
- irb(main):001:0> Page.all
- => [#<Page id: 1, title: "The Marx Brothers Wiki", slug: "Home",
- body: "An encyclopedic guide to the Marx Brothers.",
- created_at: "2010-02-21 12:24:43", updated_at: "2010-02-21 12:24:43">]
在繼續(xù)運(yùn)行編碼之前,請(qǐng)先設(shè)定路徑。需要兩條路徑:一條默認(rèn)的路徑用來查找主頁(yè)面,而另外一條路徑則通過標(biāo)頭來查找頁(yè)面。清單 9 顯示了最終版的 config/routes.rb 文件。
- 清單 9. config/routes.rb(最終版)
- Wiki::Application.routes.draw do |map|
- resources :pages
- root :to => "pages#show"
- end
在清單 6中,rails generate scaffold page 這一行命令可自動(dòng)在第二行創(chuàng)建路徑,這是 REST 式的。您必須在第三行手動(dòng)添加路徑。用于指定站點(diǎn)路徑的默認(rèn) “根目錄” 的語法是 Rails 3 中的新增功能。第三行定義的是,“將路徑 ‘/’ 映射到頁(yè)面控制器的 ‘show’ 方法”。show 方法的代碼將在數(shù)據(jù)庫(kù)中查找主頁(yè)面并顯示出來。添加新的根目錄路徑后,需要?jiǎng)h除 public/index.html 文件以避免產(chǎn)生沖突:
- $ rm public/index.html
現(xiàn)在,讓我們來關(guān)注頁(yè)面控制器。Rails 3 中的控制器代碼可以極其簡(jiǎn)單。清單 10 通過單一的 show 方法,顯示了控制器的初始實(shí)現(xiàn)。
- 清單 10. Rails 3 控制器
- class PagesController < ApplicationController
- respond_to :html
- def show
- @page = Page.where( :slug => ( params[:id] || 'Home' ) ).first
- respond_with( @page )
- end
- end
正如您所看到的,通常在 Rails 2 控制器中提供的所有模板都不見了。respond_to 列出了控制器所支持的格式;此處,它僅會(huì)對(duì) HTML 的請(qǐng)求做出反應(yīng)。respond_with 是邏輯快捷方式,用于決定控制器應(yīng)如何繼續(xù)處理。
查詢的語法也是大有不同。查詢是 Rails 3 關(guān)系代數(shù)的一個(gè)示例。您可能會(huì)想知道為什么需要有 first 后綴。where 和其他表達(dá)查詢的操作數(shù)并不會(huì)真正引起查詢語句被執(zhí)行。相反地,查詢站點(diǎn)一直閑置,直到真正需要數(shù)據(jù)時(shí)才啟動(dòng)。這就是延遲加載,即盡可能長(zhǎng)的延遲查詢語句的執(zhí)行。first 命令將觸發(fā)數(shù)據(jù)庫(kù)中的實(shí)際查詢。
如果您現(xiàn)在運(yùn)行應(yīng)用程序,您會(huì)看到與 圖 1 相似的情況,現(xiàn)在,您可以向控制器中添加更多的代碼。清單 11 顯示了完整的控制器。
- 清單 11. 完整的 Rails 3 控制器
- class PagesController < ApplicationController
- respond_to :html
- before_filter :get_page, :except => [ :create ]
- def create
- respond_with( @page = Page.create( params[ :page ] ) )
- end
- def edit
- end
- def index
- render :action => :show
- end
- def show
- @page ||= Page.new( :slug => params[ :id ] )
- if @page.new_record?
- render :action => :new
- else
- respond_with( @page )
- end
- end
- def update
- @page.update_attributes( params[ :page ] )
- respond_with( @page )
- end
- private
- def get_page
- @page = Page.where( :slug => ( params[:id] || 'Home' ) ).first ||
- Page.where( :id => params[:id] ).first
- end
- end
在該控制器中,index 方法僅僅反映沒有頁(yè)面標(biāo)示符的 show 操作,從而呈現(xiàn)主頁(yè)面。show 會(huì)顯示一個(gè)頁(yè)面,并提供一個(gè) ID 或標(biāo)頭(所有操作的查詢都集中在 get_page 中,從而進(jìn)一步減少了代碼的數(shù)量);如果某個(gè)頁(yè)面不存在,則會(huì)準(zhǔn)備一個(gè)新的頁(yè)面以供進(jìn)行編輯。Page模型僅僅可以驗(yàn)證所有顯示的字段:
- class Page > ActiveRecord::Base
- validates_presence_of :body, :slug, :title
- end
將駝峰式大小寫引用轉(zhuǎn)換為指向其他頁(yè)面的鏈接,這一工作是在 Page 模型的視圖中進(jìn)行的。由 app/helpers/pages_helper.rb 中的 helper 函數(shù)來完成這一工作,從而保持視圖的最小化(請(qǐng)參閱 清單 12)。
- 清單 12. 駝峰式大小寫轉(zhuǎn)換 helper 函數(shù)
- module PagesHelper
- def wikify( page )
- return '' if page.body.blank?
- page.body.gsub( /^([A-Z][[:alnum:]]*([A-Z][[:alnum:]]*)+)/ ) do |match|
- link_to( $1, :action => :show, :id => $1 )
- end
- end
- end
該視圖是典型的視圖,如清單 13中所示。
- 清單 13. 典型視圖
- <p>
- <b>Title:b>
- <%= @page.title %>
- p>
- <p>
- <b>Body:b>
- <%= raw wikify( @page ) %>
- p>
- <%= link_to 'Edit', edit_page_path(@page) %> |
- <%= link_to 'Back', pages_path %>
raw操作數(shù)是Rails 3中新增的功能。與以前版本的Rails不同,默認(rèn)情況下所有的字符串都可以(去掉了HTML)安全發(fā)送。如果要通過HTML發(fā)送一個(gè)字符串,則必須使用 raw。
切換Rails
除了此處所介紹的功能改進(jìn)和便捷性,Rails 3還提供了比以前版本更佳的性能,尤其是在呈現(xiàn)部件方面。您還可以創(chuàng)建您專有的驗(yàn)證器類,并充分利用更為流暢的標(biāo)準(zhǔn)驗(yàn)證。例如,由 Jeremy McAnally 編寫以下驗(yàn)證,一次需要四行單獨(dú)的代碼:
- validates :login, :presence => true, :length => {:minimum => 4},
- :uniqueness => true, :format => { :with => /[A-Za-z0-9]+/ }
【編輯推薦】