---
# System prepended metadata

title: Ruby on Rails(ROR) 詳談
tags: [Ruby on Rails]

---

# Ruby on Rails(ROR) 詳談
###### tags: `Ruby on Rails`
## 簡介
Ruby是一套開放原碼、物件導向的動態、強型別、直譯式(interpreted)程式語言，它有著簡單哲學、高生產力、精巧、自然的語法。Ruby是松本行弘(Ruby之父)於1993年2月24日開始編寫Ruby，直至1995年12月才正式公開發佈，之所以稱為Ruby是取法自Perl，因為Perl的發音與6月的誕生石pearl（珍珠）相同，Ruby選擇以7月的誕生石ruby（紅寶石）命名。

讓我們看一個非常簡單的範例：
```ruby=
str = "May Ruby be with you!"
5.times { puts str }
```
這的範例就簡單告訴我們有關Ruby的三件事情了：
動態分型(typing)，不需要宣告型態每樣東西都是物件，包括數字使用Code Block形式的匿名函式(anonymous function)隨處可見

Ruby on Rails(官方簡稱為Rails，RoR非官方簡稱)是使用Ruby這套開放原始碼(採用MIT授權)、物件導向程式語言所開發的Web開發框架，主要用於開發資料庫網站應用程式。Rails是一套專業的開發框架，採用了MVC(Model-View-Control)模式、內建支援單元測試和整合測試、支援Ajax和RESTful介面、ORM機制，以及支援各種最新的業界標準像是HTML5、JQuery等等功能。它的發明人是David Heinemeier Hanson(DHH)，DHH是2004年將Rails從37signals商業產品中獨立出來成為開源專案。而ROR有一套獨特的設計理念就是Convention over Configuration(慣例優於設定)和Don't Repeat Yourself(別重複自己)，根據這樣的設計理念，使得ROR能高效率快速開發網站。

## Ruby特性
### 1. 物件導向
物件（object） = 狀態（state） + 行為（behavior），在Ruby的世界中所有東西都是物件，數字、字串、陣列、雜湊 等等都是一種物件。**Ruby中的物件(Object)是一個類別(Class)所製造出來的實體(Instance)。** 下面舉例
```ruby=
class HelloKitty
  def say_hi
    puts "#{@name} says hi~!"
  end
end
kitty = HelloKitty.new("Kitty White")
kitty.say_hi # => Kitty White says hi~!
```
使用HelloKitty.new從HelloKitty類別中產生一個實例(instance)，並且將這個實例存於變數kitty中。並可視kitty 為HelloKitty類別的物件(Object)或者是實例(Instance)。

物件導向語言有封裝、繼承、多型三大特性，讓程式易讀易懂，容易維護，可以支持更大的系統，讓更多人可以合作，讓一切有序、簡單。在遇到需求變更的時候，有較大的靈活性可以應對。讓大型軟體工程的計劃和設計變得更容易管理，能增強工程的健康度，減少失敗工程的數量。

### 2. 直譯語言
* https://totoroliu.medium.com/%E7%B7%A8%E8%AD%AF%E8%AA%9E%E8%A8%80-vs-%E7%9B%B4%E8%AD%AF%E8%AA%9E%E8%A8%80-5f34e6bae051

* 編譯型語言
一種通過編譯器（compiler）將原始碼編譯成機器碼，透過鏈結或中間代碼將雙邊串聯才能執行的語言。
特色： 編譯器一般會有預編譯的過程對代碼進行優化，所以速度快。但一般來講可移植性較低 因為有些只能在預設的環境才能執行

* 直譯型語言
直接寫程式就可以不需編譯，但每次要執行都要解釋一遍才能執行。
特色： 有良好的兼容性，可移植到任何環境中執行。前提是必須有解釋器(直譯器或虛擬機器) 但其靈活部署快速仍然是好的選擇
### 3. 動態語言
基本上變數帶有資料型態就是靜態語言，且要事先宣告;反之就是動態語言

以 Java 為例，text 宣告為 String ，就僅可參考 String 實例，若嘗試參考至其它型態，則會引發編譯錯誤。靜態型別語言需要檢查型別，好處是可透過編譯器或工具，在程式執行前（編譯時期）就檢查出型態錯誤。也因為執行期不需要再編譯所以執行速度比動態語言快很多。
```java=
String text = "programmer";
text = {'p', 'r', 'o'}; // 編譯錯誤
```
比方Ruby中把字串令狐沖指定給區域變數a，可以知道這時變數 a 的型別是String(字串)。這時，可以改成指定整數1，型別就變成 Integer (整數)。動態型別的型態錯誤在執行時期才會呈現出來，因為執行到程式碼時才檢查形別，效能表現較不理想，編輯輔助工具較為缺乏，依賴慣例或實體文件來得知API使用方式。這種可以改變變數型別的特性，讓 Ruby 工程師可以更有彈性使用變數，不需要思考形態問題，只要思考變數參考的物件有哪些特性，也就是 OOP (物件導向語言）的特性 Duck Type (鴨子型別)。
```ruby=
a = '令狐沖'
a.class
#=> String

a = 1
a.class
#=> Integer
```
### 4. 強型別
* 強型別(strongly typed)：偏向不容許隱性型別轉換，型別檢查上較為嚴格。Ruby就是強型別，不同型態資料不能一起操作，因此會報錯。
```ruby=
number = 2;
sum = "2" + 2;
puts sum # => error
```
* 弱型別(weakly typed)：偏向容許隱性型別轉換，型別檢查上較為寬鬆。Javascript就是弱型別，雖然沒有在程式碼裡指明我想將字串 "2" 轉成數字，Javascript直譯器發現我在做算術運算，而且 "2" 可以被轉成數字，就「貼心」地自動幫忙轉成數字，然後吐出相加的結果。
```javascript!
number = 2
sum = "2" + 2
console.log(sum) // 22
```

普遍來說，強型別當然比較嚴謹，很多潛藏的 Bug 可以在編譯時期甚至撰寫時期就發現；但也代表開發過程可能需要花許多時間去雕琢語法來符合強型別的語法規範限制。

### 5. ROR兩大設計哲學
* 慣例優於設定Convention Over Configuration，例如當有一個```user``` model時，Rails就會自動在```app/models/user.rb```定義這個model讓你直接使用，並且model中的紀錄都會存放在資料庫中名為```user```的資料表中，不需要做額外設定。或是在```config/routes.rb```所設定的路徑action會直接對應到controller中的method，不需要再額外設定。

* 別重複自己Don't Repeat Yourself，例如partial render就是一個例子。或是下面也是一個例子
```ruby!
# Post model
scope :unpublished, ->(timestamp = Time.now) { where('published_at IS NULL OR published_at > ?', timestamp) } 


# Any controller
def index
    ....
    @unpublished_posts = Post.unpublished
    ....
end

def others
    ...
    @unpublished_posts = Post.unpublished
    ...
end
```

### 6. 徹底實踐MVC
* 我有簡單解釋MVC https://hackmd.io/sH8p15O8QlKsLR0Ad_wUIQ
