Rake簡(jiǎn)介
Rake的意思是Ruby Make,一個(gè)用ruby開(kāi)發(fā)的代碼構(gòu)建工具.
但是,為什么Ruby需要Rake?
按理說(shuō)Ruby代碼無(wú)需編譯,應(yīng)該不需要Rake才對(duì)呀?原來(lái),Rake另有妙用,即把Rake當(dāng)做一個(gè)任務(wù)管理工具來(lái)使用...這樣做有兩個(gè)好處:
1.以任務(wù)的方式創(chuàng)建和運(yùn)行腳本
當(dāng)然,你可以用腳本來(lái)創(chuàng)建每一個(gè)你希望自動(dòng)運(yùn)行的任務(wù).但是,對(duì)于大型的應(yīng)用來(lái)說(shuō),你幾乎總是需要為數(shù)據(jù)庫(kù)遷移(比如Rails中db:migrate任務(wù))、清空緩存、或者代碼維護(hù)等等編寫(xiě)腳本.對(duì)于每一項(xiàng)任務(wù),你可能都需要寫(xiě)若干腳本,這會(huì)讓你的管理變得復(fù)雜.那么,把它們用任務(wù)的方式整理到一起,會(huì)讓管理變得輕松很多.
2.追蹤和管理任務(wù)之間的依賴
Rake還提供了輕松管理任務(wù)之間依賴的方式.比如,"migrate"任務(wù)和"schema:dump"任務(wù)都依賴于 "connect_to_database"任務(wù),那么在"migrate"任務(wù)調(diào)用之前,"connect_to_database"任務(wù)都會(huì)被執(zhí)行.
下面入正題吧,即如何用Rake編寫(xiě)一個(gè)任務(wù)腳本..
順序執(zhí)行
在Rake中定義任務(wù)后,可以指定任務(wù)的執(zhí)行順序,例如,每天早晨起床后的例行公事:
1. 關(guān)閉鬧鐘
2. 梳洗打扮
3. 泡杯咖啡
4. 遛狗
上面的幾項(xiàng)事物,在Rakefile中這樣描述
task :turn_off_alarm do
puts "Turned off alarm. Would have liked 5 more minutes, though."
end
task :groom_myself do
puts "Brushed teeth."
puts "Showered."
puts "Shaved."
end
task :make_coffee do
cups = ENV["COFFEE_CUPS"] || 2
puts "Made #{cups} cups of coffee. Shakes are gone."
end
task :walk_dog do
puts "Dog walked."
end
task :ready_for_the_day => [:turn_off_alarm, :groom_myself, :make_coffee, :walk_dog] do
puts "Ready for the day!"
end
通過(guò)rake ready_for_the_day來(lái)執(zhí)行任務(wù),然后你就可以看到,所有的task都在按照你預(yù)定的順序在執(zhí)行。
Turned off alarm. Would have liked 5 more minutes, though.
Brushed teeth.
Showered.
Shaved.
Made 5 cups of coffee. Shakes are gone.
Dog walked.
Ready for the day!
此外還可以用過(guò)rake make_coffee COFFEE_CUPS=5這樣在命令中給變量賦值。
命名空間
上面那樣定義任務(wù)沒(méi)有問(wèn)題,但如果你需要另外定義些事物,比如工作相關(guān)的,交通相關(guān)的,這時(shí)候所有的任務(wù)混雜到一起顯然就不合適了,畢竟上面那些任務(wù)只是我們起床的例行事物,與其它無(wú)關(guān)。
通過(guò)namespace可以幫助我們定義出Rails中類(lèi)似rake db:migrate的任務(wù),描畫(huà)出事物間清晰的邊界,將上面的任務(wù)包括在namespace的一個(gè)代碼塊中,如下
namespace :morning do
task :turn_of_alarm
....
end
這一次我們的調(diào)用命令就需要稍微做出些許變化,rake COFFEE_CUPS=3 morning:ready_for_the_day。 是不是跟rails中的rake任務(wù)調(diào)用方式很像呢?
默認(rèn)Task
有了上面那些設(shè)置,如果我們忘記或者不想寫(xiě)詳細(xì)的任務(wù)名稱,直接執(zhí)行rake會(huì)有什么效果呢,結(jié)果是rake aborted!,任務(wù)被中斷的報(bào)錯(cuò)。既然有這樣的可能性,我們就需要消除這些隱患,通過(guò)設(shè)置default默認(rèn)任務(wù)就可以做到,如下:
task :default => 'morning:turn_off_alarm'
當(dāng)你直接執(zhí)行rake命令時(shí),會(huì)執(zhí)行默認(rèn)操作,幫我們關(guān)閉鬧鐘。
描述你的Task
當(dāng)任務(wù)漸漸變多以后,管理問(wèn)題就暴露出來(lái)了,除了命名空間以外,我們還需要文檔類(lèi)的支持,幫助我們梳理任務(wù)并顯示的告訴我們每個(gè)任務(wù)的目的和功能,這時(shí)你可以試一試用desc描述任務(wù)。
...
desc "Make coffee"
task :make_coffee do
cups = ENV["COFFEE_CUPS"] || 2
puts "Made #{cups} cups of coffee. Shakes are gone."
end
...
上面的描述不僅可以在文檔中查看,同時(shí)使用rake -T也能清洗的了解到每個(gè)任務(wù)是做什么的。rake -T的輸出結(jié)果是按照字母順序排的序。
rake morning:make_coffee # Make coffee
調(diào)取Task
Rake還允許在不同任務(wù)之間互相調(diào)用,例如下面的代碼,你想在下午也來(lái)杯咖啡,不用重復(fù)定義,直接使用上午的泡法,來(lái)一杯即可。
namespace :afternoon do
task :make_coffee do
Rake::Task['morning:make_coffee'].invoke
puts "Ready for the rest of the day!"
end
end
Rake腳本編寫(xiě)
先來(lái)個(gè)簡(jiǎn)單的例子,如下:
假設(shè)你是一個(gè)火星成員,老版本那些,即如燕兒虎跑之類(lèi)的,在周末你打算去車(chē)車(chē)那邊打火鍋,然后集體PC去.對(duì)應(yīng)這個(gè)情況,你需要為自己制定三個(gè)任務(wù):搭車(chē)找車(chē)車(chē)、烤魚(yú)和網(wǎng)吧PC.用vim創(chuàng)建創(chuàng)建一個(gè)名叫rakefile的文件(備注:Rake會(huì)在當(dāng)前路徑下尋找名叫Rakefile、rakefile、RakeFile.rb和rakefile.rb的rake文件),并鍵入如下代碼:
desc "任務(wù)1 -- 搭車(chē)去車(chē)車(chē)那里"#這據(jù)說(shuō)是個(gè)苦差,因?yàn)樘h(yuǎn)了
task :busboy do
puts "發(fā)現(xiàn)挫男"
end
desc "任務(wù)2 -- 烤魚(yú)"
task :bitchfish do
puts "老板,先烤九斤魚(yú)"
end
desc "任務(wù)3 -- 網(wǎng)吧PC"
task :pc do
puts "我選中路"
end
打開(kāi)命令行工具,進(jìn)入這個(gè)文件所在目錄,然后運(yùn)行下面的命令,大致應(yīng)該類(lèi)似如下結(jié)果:
D:\work>rake busboy
(in D:/work)
發(fā)現(xiàn)挫男
D:\work>rake bitchfish
(in D:/work)
老板,先烤九斤魚(yú)
D:\work\ruby_works\ruby_book>rake laundry
(in D:/work)
我選中路
(備注:文字部分是沒(méi)啥邏輯的,純粹娛樂(lè)下...)
分析:
相信看完上面那段東東,你已經(jīng)知道怎么搞了...現(xiàn)在介紹些基礎(chǔ)知識(shí),方便加深理解.從上面的代碼可以知道,此文件一共定義了3個(gè)任務(wù),desc是Rake定義的方法,表示對(duì)下面定義任務(wù)的描述.這個(gè)描述會(huì)在使用Rake --tasks(或者Rake -T)命令時(shí)輸出在屏幕上.
D:\work>rake --tasks
(in D:/work)
rake bitchfish #任務(wù)2 -- 烤魚(yú)
rake busboy #任務(wù)1 -- 搭車(chē)去車(chē)車(chē)那里(這據(jù)說(shuō)是個(gè)苦差,因?yàn)樘h(yuǎn)了)
rake pc 任務(wù)3 -- 網(wǎng)吧PC
task是Rake最重要的方法.它的方法定義是:task(args, block).任務(wù)體是一個(gè)block,本例中只是簡(jiǎn)單輸出你所要做的工作.需要注意的是代碼
完全是一個(gè)普通的Ruby語(yǔ)句,puts是Ruby中進(jìn)行輸出的一般性方法,可以看出,Rake任務(wù)可以完全使用Ruby的能力,這使得它非常強(qiáng)大.
go..go..go..go..
接下來(lái)加入依賴關(guān)系:
很顯然,在我們定義的任務(wù)中,"烤魚(yú)"是依賴于"搭車(chē)去車(chē)車(chē)那里"的(其它地方有沒(méi)烤魚(yú)吃不知道,反正地點(diǎn)就定在那了).那么,我們需要在我們的任務(wù)定義中加入這個(gè)依賴關(guān)系,修改后的文件如下:
desc "任務(wù)1 -- 搭車(chē)去車(chē)車(chē)那里"
task :busboy do
puts "發(fā)現(xiàn)挫男"
end
desc "任務(wù)2 -- 烤魚(yú)"
task :bitchfish => :busboy do
puts "老板,先烤九斤魚(yú)"
end
desc "任務(wù)3 -- 網(wǎng)吧PC"
task :pc do
puts "我選中路"
end
再次運(yùn)行烤魚(yú)任務(wù),你會(huì)得到如下結(jié)果:
D:\work>rake bitchfish
(in D:/work)
發(fā)現(xiàn)挫男
老板,先烤九斤魚(yú)
加入命名空間:
跟任何編程語(yǔ)言類(lèi)似,當(dāng)你的rake文件很多時(shí),當(dāng)你有很多任務(wù)的時(shí)候,你需要關(guān)注它們的命名沖突問(wèn)題,命名空間(namespace)就是一個(gè)自然的解決方案.你可以為上面的三個(gè)任務(wù)定義一個(gè)叫做dan的命名空間.
namespace :dan do
desc "任務(wù)1 -- 搭車(chē)去車(chē)車(chē)那里"
task :busboy do
puts "發(fā)現(xiàn)挫男"
end
……
end
再次運(yùn)行rake --tasks,你會(huì)得到如下的結(jié)果:
D:\work >rake --tasks
(in D:/work)
rake dan:bitchfish # 任務(wù)2 -- 烤魚(yú)
rake dan:pc # 任務(wù)3 -- 網(wǎng)吧PC
rake dan:busboy # 任務(wù)1 -- 搭車(chē)去車(chē)車(chē)那里
你現(xiàn)在需要使用rake dan:bitchfish才能啟動(dòng)烤魚(yú)這個(gè)任務(wù)了.
(BTW,你可以在你的rakefile中使用多個(gè)命名空間,對(duì)任務(wù)進(jìn)行分類(lèi).)
了解了上面兩個(gè)知識(shí)點(diǎn)后,我們來(lái)了解下兩個(gè)具體實(shí)例:
1.在一個(gè)任務(wù)中調(diào)用另外一個(gè)任務(wù)
當(dāng)任務(wù)眾多的時(shí)候,你很可能需要在一個(gè)任務(wù)中調(diào)用另外一個(gè)任務(wù),假設(shè)我們把今天所有要做的工作定義為一個(gè)任務(wù):today.在這個(gè)任務(wù)中,有兩個(gè)任務(wù)需要被調(diào)用,一個(gè)是烤魚(yú),一個(gè)是網(wǎng)吧PC.當(dāng)然,由于烤魚(yú)依賴于搭車(chē)去車(chē)車(chē)那里,我們還是需要搭車(chē)去車(chē)車(chē)那里的.在文件的頂部定義一個(gè)today的任務(wù):
desc "今天的任務(wù)"
task :today do
Rake::Task["dan:bitchfish"].invoke
Rake::Task["dan:pc"].invoke
end
namespace :dan do
……
end
可以看出,調(diào)用其它任務(wù)的方式很簡(jiǎn)單,只需要調(diào)用
Rake::Task["task_name"].invoke
方法就可以了.在命令行中啟動(dòng)rake today,可以得到:
D:\work >rake today
(in D:/work)
發(fā)現(xiàn)挫男
老板,先烤九斤魚(yú)
我選中路
2.默認(rèn)任務(wù):
可以為Rake增加一個(gè)默認(rèn)任務(wù),這樣可以簡(jiǎn)單地用Rake命令來(lái)觸發(fā)這個(gè)默認(rèn)任務(wù),在上面的rakefile中,我們可以用如下方式把"today"任務(wù)作為默認(rèn)任務(wù).
task :default => [:today]
然后調(diào)用直接在命令行中調(diào)用rake,可以得到跟調(diào)用rake today同樣的輸出結(jié)果.
這就是我們簡(jiǎn)單的一個(gè)Rake任務(wù)定義,下面是完整的修改后的rakefile:
task :default => [:today]
desc "今天的任務(wù)"
task :today do
Rake::Task["dan:bitchfish"].invoke
Rake::Task["dan:pc"].invoke
end
namesoace :dan do
desc "任務(wù)1 -- 搭車(chē)去車(chē)車(chē)那里(這據(jù)說(shuō)是個(gè)苦差,因?yàn)樘h(yuǎn)了)"
task :busboy do
puts "發(fā)現(xiàn)挫男"
end
desc "任務(wù)2 -- 烤魚(yú)"
task :bitchfish do
puts "老板,先烤九斤魚(yú)"
end
desc "任務(wù)3 -- 網(wǎng)吧PC"
task :pc do
puts "我選中路"
end
end
看完上面兩個(gè)例子,估計(jì)rake任務(wù)就算全部了解了...其它都是些代碼槍花罷了..多耍便是..
您可能感興趣的文章:- 學(xué)習(xí)Ruby你需要了解的相關(guān)知識(shí)(rvm, gem, bundle, rake, rails等)