為你自己學 Ruby on Rails(第二版)- 第一章 簡介及生態圈

為你自己學 Ruby on Rails(第二版)- 第一章 簡介及生態圈

Ruby 生態圈

本書正在連載、撰寫中,待完稿後會集結成冊出版

Ruby 這個程式語言可以說是因為 Rails 的盛行而興起的也不為過,我認識大部份的人會開始學習 Ruby 或知道 Ruby 這個程式語言,大多也是因為 Rails 的緣故。事實上,目前我所知道大部份在使用 Ruby 進行開發的專案,大部份也都是 Rails 相關的專案。

關於 Ruby

什麼是 Ruby?

我相信很多人因為聽聞 Rails 可以快速開發網站而開始知道有 Ruby 這個程式語言(甚至認為 Rails 是一種程式語言),所以會認為 Ruby 主要就是用來開發網站,或是以為 Ruby 是近幾年才新發明的程式語言。事實上 Ruby 是一種泛用的腳本式程式語言,從資料分析、繪圖、3D 建模、系統管理、遊戲開發等程式都可以使用 Ruby 來開發,而且它的年紀說不定比各位讀者還要大,Ruby 目前已經已經超過 25 歲了。

Ruby 是由一位名叫松本行弘的日本人所發明的(日文:まつもとゆきひろ,網路上大家通常稱他 Matz)。發明人 Matz 當年參考了部份 Perl、Lisp 及 Smalltalk 等程式語言的設計,開發出一款更容易撰寫、語法寫起來更像一般人類語言的程式語言。

Matz 在 1993 年開始設計,於 1995 年釋出了第一個版本。早期使用 Ruby 的開發者並不算多,相關的技術文件也大多是日文居多,直到 Rails 開始風行之後,才慢慢的有越來越多人關注它,並於 2006 年獲選為 TIOBE 年度程式語言。Ruby 目前在 TIOBE 網站上的排行榜一直都在前 20 名的位置,以全世界眾多程式語言來說,算是前段班的位置。

為什麼選擇 Ruby

引用一句已故大師 Alan Perlis 的話:

"A language that doesn't affect the way you think about programming is not worth knowing" — Alan Perlis

翻成中文意思是:

「如果這個程式語言不會影響你寫程式的思考方式的話,那就不值得去學習它。」

Ruby 是個很容易學、很容易上手的程式語言,語法寫起來也很自然、有趣,也因為 Ruby 的自然語法,寫久了真的會影響你在寫程式時候的思考或設計方式。

Ruby 的語法寫起來很自然,所以用 Ruby 寫出來的程式碼的可閱讀性也相當高。不管是接手別人的專案,或是維護自己幾個月前寫的系統,比較好的程式碼可讀性對開發者來說可以減少不少負擔。

另外,現在全世界的 Ruby 社群都相當活躍,要找什麼套件幾乎都有熱心人士幫忙寫好了。除了可以免費取得之外,連原始程式碼都公開給你看。在台灣,Ruby 社群也十分活躍,雖然因為疫情的影響而減少了很多實體的線下聚會,但網路社團的討論風氣還是相當好的。

在本文撰寫的當下,官方最新推出的 Ruby 穩定版本是 3.1.2 版,較舊版本的 Ruby(1.8、1.9 或更早之前)的部份功能也可能會被提出來做為比較。本書將會以 3.1.2 版本為主,不過由於 Ruby 的向下相容性,即使是使用比較舊的版本都還是能正常運作。

不同版本的 Rails 對 Ruby 也有不同的最低的需求:

本書因為使用 Rails 6 / 7 為主,所以請安裝 Ruby 2.5 或 2.7 以上版本,建議直接上 Ruby 3 系列版本,除了加了更多新功能之外,效能也更好一些。

誰在用 Ruby?

很多人在評估程式語言的優劣,是看有哪些大公司、單位在使用它,或是使用的開發者人數。老實說我個人不是很在意這個問題,有些人覺得 Ruby 並不是很流行,在 TIOBE 網站上的排名也不是最流行的,但我個人認為,好的東西並不需要流行(反之,流行的也不一定是好東西),只要能完成任務的工具就是好工具。在 iPhone 還沒流行之前,誰也沒料到開發 iOS app 的 Objective-C 這個語法看起來很奇怪的程式語言有一天可以這麼熱門,然後也不會知道 Apple 自家的後起之秀的 Swift 把打趴在沙灘上。

關於 Rails

什麼是 Rails?

Rails 是一款使用 Ruby 程式語言所開發出來的網站開發框架(Web Framework),作者是 David Heinemeier Hansson(簡稱 DHH) 。當年他在開發自家的產品(Basecamp)的同時,發現好像可以把一些網站開發常用的模組或函式庫慢慢的組成一個框架,而且利用這個框架可以大幅的縮短網站應用程式開發的時間。DHH 在 2005 年年底釋出第一個版本,並在研討會現場火力展示了如何使用 Rails 在 15 分鐘內開發出一個 Blog,讓所有的人眼睛為之一亮。在那之後,Rails 開始慢慢的風行到全世界,也讓更多人開始關注 Ruby 這個有趣的程式語言。現在市面上常見的網站開發框架的設計(例如 PHP 的 Laravel),多少也直接或間接的受了 Rails 的影響。

一開始大家會把 Ruby on Rails 簡稱為「RoR」,不過因為「RoR」實在不好發音,後來大家開始慢慢的改稱之 Rails,包括本書也是。

有些朋友在學習 Rails 過程中曾問道「既然 Rails 這麼方便,那有必要學 Ruby 嗎?」。我的建議是:「是的,有必要!」。你也許不需要把 Ruby 學得非常熟、不需要背下 Ruby 標準函式庫裡的所有方法,但至少你該學在 Rails 專案裡常看到的 Ruby 語法。

很多人一開始可能搞不清楚 Ruby 跟 Rails 之間的關係,甚至會以為 Ruby on Rails 就是一種程式語言。如果打個比方的話,大家也許看過或玩過樂高(Lego)積木,Rails 就像是一塊一塊的積木,可以讓你很快的把城堡蓋起來;而 Ruby 則像是積木的原料(塑膠),沒有原料就不會有這個積木。

Ruby 是一款設計很特別、寫起來也很有趣的程式語言,如果能花時間更去深入 Ruby 這個程式語言特別的點,相信在寫 Rails 的時候可以寫出更漂亮、簡潔、有效率的語法。

Rails 設計哲學

在 Rails 世界有兩個主要的設計哲學:

慣例優於設定(Convention over Configuration, CoC)

所謂的「慣例」就是不成文的規定,當遇到某種情況的時候我們會用特定的方式來解決問題,或是該把某個功能的程式碼放在什麼地方。然而即然是不成文的慣例,所以就算不照著慣例寫,也有別的方法可以達到一樣的目的,只是可能得多寫一些程式碼就是了。

在 Rails 裡有非常多這樣的慣例,例如像是整個專案的目錄結構、資料表的關連、單複數命名等。順著 Rails 的慣例,程式碼可以變得更簡潔、優雅。甚至可以說在學習 Rails 的過程,除了學習 Ruby 或 Rails 的語法之外,也是在學習 Rails 的慣例。

不要做重複的事(Don't Repeat Yourself, DRY)

如果有些程式碼一直重複的出現,就應該把重複的部份抽離出來,整理成為一個方法、類別或模組。這樣不僅可以重複使用,也會因此變得比較好維護,有發生問題也比較容易被發現。

跟 DRY 相反,如果沒有好好的整理,一直寫著重複的程式碼,有時也會開玩笑說這樣的程式碼很不 DRY、有點 WETWrite Everything Twice),很潮、潮到出水了!

常見問題

聽說寫 Ruby/Rails 要先買 Mac 電腦?

早期 Ruby/Rails 的開發者幾乎人手一台 Mac 筆電,會有種好像要寫 Ruby/Rails 就得先買台 Mac 電腦。但其實不需要,使用 Mac OS 作業系統只是在開發環境比較方便,相關的工具也比較多,但並不是必需品,即使用一般的 PC,只要安裝 Linux/Ubuntu 系統一樣可以進行開發。事實上,大部份的 Rails 網站部署的環境也都是 Linux/Ubuntu,所以不要聽信「要先學 Ruby/Rails 要先買 Mac 電腦」之類的都市傳說。

當然,如果經濟許可或是剛好要採購新電腦,這年頭的 Mac 筆電效能大躍進,新款的 M1 或 M2 晶片的筆電效能又好又省電,是個很不錯的選擇。就我自己用 Mac 十餘年的經驗,使用 Mac 電腦開發 Ruby/Rails 專案是件很開心的事,至少不用太擔心開發環境的問題,而且很多好用的開發工具甚至都是 Mac 作業系統限定。

Windows 的使用者也不用太擔心,現在 Windows 上有 WSL(Windows Subsystem for Linux)可以用,整個用起來的手感跟一般的 Ubuntu 沒太大的差別,跟 Windows 的整合度也不錯,甚至如果配合 VSCode 的某些擴充套件,幾乎會感受不到 WSL 的存在,基本上用來開發 Ruby/Rails 應用程式沒什麼太大問題。

聽說 Ruby/Rails 很慢?

這點我不會否認,如果要比較的話,Ruby 的執行效能的確不算是前段班的。不過快或慢是相對的比較值,所以就要看是跟誰比。以市面上常見的的程式語言來說,單就要比執行效能的話,如果跟 C / C++ / Go / Rust 之類的系統程式語言相比當然是慢。

而 Rails 為了整體的功能完整性,它不知不覺的長大成一個有點肥胖的框架,以一個全新建立的 Rails 應用程式來說,光是啟動就會吃掉不少記憶體。不過 Ruby/Rails 並沒有慢到不堪使用的程度,而且業界許多大流量網站用 Ruby/Rails 也是跑的很順(其實很多時候是寫的人不會寫...)

Ruby 的特點,在於可以用自然、簡短的語法開發出你想要的功能,而 Rails 的重點則是可以快速的打造出產品雛型,讓產品早點上線試一下水溫,先試試商業模式是否可以運作,如果真的有人買單,再來擔心效能也不遲。後續如果真的有做起來的話,需要比較好的效能的部份可再考慮改用其它效能較好的程式語言改寫,業界比較大規模、大流量的網站大多也不會只使用單一技術開發。如果在一開始挑選工具的時候就在擔心「如果我的網站到時候有百萬或千萬會員流量會不會撐不住...」就有點想太遠了,這就跟「如果我中了樂透有很多錢花不完怎麼辦」一樣,這種「有錢人的煩惱」,可以等真的有錢再來煩惱就好。

遊戲圈有一句名言「死人沒有 DPS(Damage Per Second)」,意思就是手上握有再強大的武器,但只是躺在地上看星星也是沒用的。同理,若使用強大效能的程式語言或框架但開發時程較長而錯過市場時機,效能再快、再好也是沒有用的。

Rails 的前端生態

身為 Ruby/Rails 工程師,習慣 Ruby 的簡潔語法以及 Rails 的 CRUD 的慣例之後,對於撰寫 JavaScript 多少有些不習慣甚至是反感,所以早年有人另外開發出 CoffeeScript 之類的工具來轉譯成 JavaScript 程式碼,在 Rails 生態圈也還流行了好一陣子。但隨著 ES6(ECMAScript 6)的推出以及各家瀏覽器對 ES6 的支援度越來越高,原生的 JavaScript 變的比較好寫,CoffeeScript 的好處逐漸變的沒那麼明顯,Rails 甚至連原本預設依賴的 jQuery 套件都拆掉了。

除此之外,早期很多的前端套件(像是 jQuery 以及 Bootstrap)也都有不少善心人士會直接把它打包成 Gem,減少許多需要撰寫 JavaScript 的機會。只是,前端的發展實在變化太快,前端套件更新版本之後還得等人包成 Gem 也不是辦法...。前端有不少像是 Webpack 之類的打包工具越來越成熟,在 Rails 專案裡原本處理圖片、CSS 以及 JavaScript 的 Assets Pipeline 也加入了 Webpacker,除了打包速度變快外,在 JavaScript 的撰寫方式也有些不同。

提到打包工具,就不得不提一下在古老的 Rails 3 時代所使用 Assets Pipeline,它最主要的用途就是把這些所謂的「資產(Assets,泛指圖片檔、字型檔、CSS 以及 JavaScript 之類的靜態檔案)」打包、改名並放置在適當的位置,就以在單純 Rails 的環境來說,Assets Pipeline 在早期還不錯用。

但隨著專案越來越複雜,Assets Pipeline 也慢慢浮出了一些問題,其中一個問題,對,就是慢。前面也提到,Ruby 本身就不算是速度快的程式語言,用 Ruby 來進行檔案的編譯、打包雖然還是可以做的不錯,但就是不夠快,特別是專案越大、前端的功能越多、越複雜,打包的過程會慢的越明顯。

隨著前端技術越來越複雜,前端圈也有自己的打包工具,例如 GulpGruntBower 以及 Webpack 等等,其中目前 Webpack 算是市佔率比較高的。只是,Webpack 的設定檔,聽說是出了名的複雜,通常設定過一次就不會想再設定第二次。

從 Rails 5.1 開始,Webpack 就變成 Rails 專案的選配設定,只要在建立專案的時候加上適當的參數就直接可以使用 Webpack 來進行打包。原本我 Assets Pipeline 用得好好的,也不是很想面對 Webpack 之類的前端打包工具,但從 Rails 5.1 開始變成選配,到 Rails 6 變成標準配備,不面對也不行了…而到了 Rails 7 又改了!前端的部份引進了 Import Maps,直接就捨棄了一大包的 node_modules 目錄。

前端除了打包工具的變化外,隨著 React、Vue 以及 Angular 之類的前端開發框架問世,對 Rails 的前端生態造成更大的變化,有些專案就直接讓 Rails 只當 API,讓 React 或 Vue 之類的前端框架取代原本 MVC(Model、View、Controller)架構裡的 View,改成前後端分離的架構。

即便 React 或 Vue 這些前端框架功能很強大,但 Rails 團隊並沒有直接就整個引進,而是另外開發了名為 Stimulus 的前端框架,它可以讓 Rails 工程師寫一個簡單的 JavaScript 類別,搭配簡單的生命週期就能控制或操作畫面上的元素。到了 Rails 7,還有個叫做 Hotwire 的新玩意兒,它可以讓開發者在不太需要寫 JavaScript 程式的情況下就能做到原本單頁式應用程式(SPA, Single-Page Application)的效果,十分神奇,而且它也是 Rails 7 的重點之一。

雖然 DHH 對 Rails 的走向有很強烈的個人意見,而且並不是每個人都認同,但在我看來,Rails 是一個很敢衝也很敢做出改變的網站開發框架,每次的變更是不是改的比較好我不敢講,但如果不試試看怎麼會知道是好是壞呢 :)

本書將會以 Rails 6 跟 7 為主,關於 Hotwire 跟 Stimulus 在本書也會在後續的章節另做介紹。