[轉載]比較冷幽默的rake使用指南

          Posted on 2008-05-09 16:19 xan 閱讀(811) 評論(0)  編輯  收藏 所屬分類: script language
          原文地址: http://blog.csdn.net/smilewater/archive/2007/07/09/1683808.aspx

          RakeMakeAnt

          Rake的意思是Ruby Make,一個用ruby開發的代碼構建工具。Rake的英文意思是耙子,一種很樸實的勞動工具。真的是很貼切,Rake正是一個功能強大、勤勤懇懇的勞動工具。

          Rake會經常跟C/C++領域的makeJava世界的Ant進行對照,事實上,它們有很多相似的地方。我們先來看一下makeant的歷史。

          make的出現是為了解決批量編譯的問題。對于一個小型的項目來說,用一個腳本文件或者批處理命令來進行批量編譯就已經足夠好。但是對于大型的項目來說,僅僅為了少數幾個文件的改變就全部重新進行一次編譯無疑是耗時且不必要的。而且,在大型的項目中,往往會有很復雜的依賴關系。

          Make的出現就是為了解決這兩個問題,make有兩個優點:

          1. Make了解自上次Make運行以來哪些文件發生了變化,它會僅僅編譯那些發生變化的文件。

          2. Make會跟蹤文件之間的依賴性,如果文件A依賴于文件B,那么如果兩者都沒有編譯時,Make會首先編譯文件B

          Ant算是一個Java世界的make,它要比make年輕許多(想想make是出現在1972年吧),它除了支持批量編譯之外,還支持單元測試、JavaDoc等任務。因此,AntJava世界中比Make更加流行。

          但是,為什么Ruby需要Rake

          Ruby代碼不需要編譯,為什么需要Rake?其實,與其說Rake是一個代碼構建工具,不如說Rake是一個任務管理工具,通過Rake我們可以得到兩個好處:

          1. 以任務的方式創建和運行腳本

          當然,你可以用腳本來創建每一個你希望自動運行的任務。但是,對于大型的應用來說,你幾乎總是需要為數據庫遷移(比如Railsdb:migrate任務)、清空緩存、或者代碼維護等等編寫腳本。對于每一項任務,你可能都需要寫若干腳本,這會讓你的管理變得復雜。那么,把它們用任務的方式整理到一起,會讓管理變得輕松很多。

          1. 追蹤和管理任務之間的依賴

          Rake還提供了輕松管理任務之間依賴的方式。比如,“migrate”任務和“schemadump”任務都依賴于 “connect_to_database”任務,那么在“migrate”任務調用之前,“connect_to_database”任務都會被執行。

          在哪里可以獲得Rake

          Rake的主頁是在http://rake.rubyforge.org/,在這里你可以獲得Rake的簡單介紹,API以及一些有用文檔的鏈接。可以在http://rubyforge.org/frs/?group_id=50獲得最新版的Rake,在作者寫作時,最新版本是0.7.3

          Rake腳本編寫

          一個簡單腳本

          Rake的腳本相當簡單,下面用一個例子進行說明。假設你是一個勤勞的家庭型程序員,在周末你打算為你的家人做一些貢獻。所以你為自己制定了三個任務:買菜、做飯和洗衣服。打開你的文本編輯器,創建一個名叫rakefile的文件(Rake會在當前路徑下尋找名叫RakefilerakefileRakeFile.rbrakefile.rbrake文件),并輸入如下內容:

          desc "任務1 -- 買菜"
          task :purchaseVegetables do
          puts "
          到沃爾瑪去買菜。"
          end

          desc "
          任務2 -- 做飯"
          task :cook do
          puts "
          做一頓香噴噴的飯菜。"
          end

          desc "
          任務3 -- 洗衣服"
          task :laundry do
          puts "
          把所有衣服扔進洗衣機。"
          end


          打開命令行工具,進入這個文件所在目錄,然后運行下面的命令,大致應該類似如下結果:

          D:"work"ruby_works"ruby_book>rake purchaseVegetables
          (in D:/work/ruby_works/ruby_book)
          到沃爾瑪去買菜。

          D:"work"ruby_works"ruby_book>rake cook
          (in D:/work/ruby_works/ruby_book)
          做一頓香噴噴的飯菜。

          D:"work"ruby_works"ruby_book>rake laundry
          (in D:/work/ruby_works/ruby_book)
          把所有衣服扔進洗衣機。


          分析

          很簡單,也很易讀,對吧。這個文件一共定義了3個任務,descRake定義的方法,表示對下面定義任務的描述。這個描述會在使用Rake --tasks(或者Rake -T,為懶人準備的快捷方式)命令時輸出在屏幕上。

          D:"work"ruby_works"ruby_book>rake --tasks
          (in D:/work/ruby_works/ruby_book)
          rake cook #
          任務2 -- 做飯
          rake laundry #
          任務3 -- 洗衣服
          rake purchaseVegetables #
          任務1 -- 買菜


          下面的語句定義了purchaseVegetables這個任務,taskRake最重要的方法。它的方法定義是:task(args, &block)。任務體是一個block,本例中只是簡單輸出你所要做的工作。需要注意的是代碼

          puts "到沃爾瑪去買菜。"

          完全是一個普通的Ruby語句,putsRuby中進行輸出的一般性方法,可以看出,Rake任務可以完全使用Ruby的能力,這使得它非常強大。

          加入依賴關系

          很顯然,在我們定義的任務中,做飯是依賴于買菜的(我相信大多數程序員在周末的冰箱里除了可樂沒有別的)。那么,我們需要在我們的任務定義中加入這個依賴關系,修改后的文件如下:

          desc "任務1 -- 買菜"
          task :purchaseVegetables do
          puts "
          到沃爾瑪去買菜。"
          end

          desc "
          任務2 -- 做飯"
          task :cook => :purchaseVegetables do
          puts "
          做一頓香噴噴的飯菜。"
          end

          desc "
          任務3 -- 洗衣服"
          task :laundry do
          puts "
          把所有衣服扔進洗衣機。"
          end


          再次運行做飯任務,你會得到如下結果:

          D:"work"ruby_works"ruby_book>rake cook
          (in D:/work/ruby_works/ruby_book)
          到沃爾瑪去買菜。
          做一頓香噴噴的飯菜。


          是的,你當然需要先買菜,誰讓你是一個冰箱空空如野的程序員呢。

          命名空間

          跟任何編程語言類似,當你的rake文件很多時,當你有很多任務的時候,你需要關注它們的命名沖突問題,命名空間(namespace)就是一個自然的解決方案。你可以為上面的三個任務定義一個叫做home的命名空間。

          namespace :home do
          desc "
          任務1 -- 買菜"
          task :purchaseVegetables do
          puts "
          到沃爾瑪去買菜。"
          end
          ……
          end


          再次運行rake --tasks,你會得到如下的結果:

          D:"work"ruby_works"ruby_book >rake --tasks
          (in D:/work/ruby_works/ruby_book)
          rake home:cook #
          任務2 -- 做飯
          rake home:laundry #
          任務3 -- 洗衣服
          rake home:purchaseVegetables #
          任務1 -- 買菜


          你現在需要使用rake home:cook才能啟動做飯這個任務了。當然,你可以在你的rakefile中使用多個命名空間,對任務進行分類。

          在一個任務中調用另外一個任務

          當任務眾多的時候,你很可能需要在一個任務中調用另外一個任務,假設我們把今天所有要做的工作定義為一個任務:today。在這個任務中,有兩個任務需要被調用,一個是做飯,一個是洗衣服。當然,由于做飯依賴于買菜,我們還是需要買菜的(這一步是逃不過去的,呵呵)。在文件的頂部定義一個today的任務:

          desc "今天的任務"
          task :today do
          Rake::Task["home:cook"].invoke
          Rake::Task["home:laundry"].invoke
          end

          namespace :home do
          ……
          end


          可以看出,調用其它任務的方式很簡單,只需要調用Rake::Task["task_name"].invoke 方法就可以了。在命令行中啟動rake today,可以得到:

          D:"work"ruby_works"ruby_book >rake today
          (in D:/work/ruby_works/ruby_book)
          到沃爾瑪去買菜。
          做一頓香噴噴的飯菜。
          把所有衣服扔進洗衣機。


          默認任務

          可以為Rake增加一個默認任務,這樣可以簡單地用Rake命令來觸發這個默認任務,在上面的rakefile中,我們可以用如下方式把“today”任務作為默認任務。

          task :default => [:today]

          然后調用直接在命令行中調用rake,可以得到跟調用rake today同樣的輸出結果。

          這就是我們簡單的一個Rake任務定義,下面是完整的修改后的rakefile

          task :default => [:today]

          desc "
          今天的任務"
          task :today do
          Rake::Task["home:cook"].invoke
          Rake::Task["home:laundry"].invoke
          end

          namespace :home do

          desc "
          任務1 -- 買菜"
          task :purchaseVegetables do
          puts "
          到沃爾瑪去買菜。"
          end

          desc "
          任務2 -- 做飯"
          task :cook => :purchaseVegetables do
          puts "
          做一頓香噴噴的飯菜。"
          end

          desc "
          任務3 -- 洗衣服"
          task :laundry do
          puts "
          把所有衣服扔進洗衣機。"
          end
          end


          Rails中的Rake任務

          Rails預定義了大量的Rake任務,在Rails應用的開發過程中,你想必已經在大量使用它們了。在Rails中,所有的Rake任務都放在rails目錄的lib/tasks目錄下(在作者的環境下是c:"ruby"lib"ruby"gems"1.8"gems"rails-1.1.4"lib"tasks"),所有的rake任務都以.rake作為后綴名,這些以.rake結尾的文件會被自動加載到你的環境中。你可以到一個已有的Rails工程根目錄下鍵入rake --tasks,可以看到很多的rake任務已經為你整裝待發了。

          Rails中,最常使用的Rake任務之一是進行數據庫的遷移(migration)。數據庫遷移程序允許你使用Ruby腳本來定義數據庫模式,而db:migrate就是進行這個工作的rake任務。下面我們來分析這個rake任務。

          db:migrate任務

          db:migrate任務存放在lib/tasks/databases.rake文件中。這個文件中定義了所有與數據庫操作相關的任務,我們僅僅抽出db:migrate的定義:

          namespace :db do
          desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x"
          task :migrate => :environment do
          ActiveRecord::Migrator.migrate("db/migrate/", ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
          Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
          end
          ……
          end



          分析

          首先是命名空間的聲明,migrate任務的命名空間是db。這也就是我們用db:migrate來引用它的原因。

          下面是一個描述,說明該任務的功能是把定義在db/migrate目錄下(相對于你的Rails應用程序的根目錄)的遷移腳本遷移到數據庫中,如果不指定VERSION的話,默認是最新版本,否則可以恢復到一個指定的版本。

          接著是任務的定義,該任務依賴于enviroment任務,這個任務在misc.rake中定義,用來加載Rails的環境,它的定義相當簡單:

          task :environment do
          require(File.join(RAILS_ROOT, 'config', 'environment'))
          end


          用來加載config/environment.rb文件,該文件會加載Rails工作所需要加載的環境。由于加載了這個環境,所以ActiveRecord對象現在可以使用,下面就是調用ActiveRecord::Migrator.migrate方法對每個db/migrate/下的腳本文件進行遷移。

          最后會調用db:schema:dump任務,該任務的主要作用是產生db/schema.rb文件。該文件用來記錄不同版本的數據庫模式。這個任務的定義就在db:migrate任務下面不遠的地方,有興趣的讀者可以自行進行分析。

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          posts - 36, comments - 2, trackbacks - 0, articles - 0

          Copyright © xan

          主站蜘蛛池模板: 巩义市| 繁昌县| 韶山市| 汨罗市| 浙江省| 越西县| 苏州市| 肥城市| 龙泉市| 南城县| 微山县| 襄垣县| 勐海县| 商河县| 安平县| 女性| 贵州省| 祁阳县| 陵川县| 宽甸| 铅山县| 时尚| 博兴县| 栾城县| 蓬溪县| 桦甸市| 蓬莱市| 清水县| 牙克石市| 兴仁县| 承德县| 平南县| 师宗县| 女性| 平泉县| 霍林郭勒市| 沙洋县| 大足县| 甘泉县| 凤冈县| 巩义市|