9. Ruby on Rails

簡介: Ruby On Rails 是以Ruby開發的Web Framework,用來開發有資料庫的網頁程式,完全物件導向、靈活有彈性、豐富的程式庫、簡易讀的語法、還有各種小訣竅能讓程式簡短。是一開放原始碼,並可以在Mac、Linux、Windows上運作。觀念上是以利用慣例優於組態(convention over configuration),軟體精簡(less software)與越快越有生產力(programmer happiness ultimately leads to better productivity)。完全的MVC架構,資料庫這部份(Active Record)是Ruby on Rails最強大的功能。

談到 Ruby 程式語言, 就不得不先提到他的物件導向 ( Object-Oriented,程式設計人員習慣簡稱 OO ) 技術, 相較於前期的里程碑 JAVA, Ruby 的物件導向更加徹底, 而且使用起來也較其他物件導向語言更加方便; Ruby 本身更提供了很多方便的方法 ( Method ) , 可讓程式開發的速度更加直覺以及口語化. 但所謂「口語化」也得在粗略地懂一些英文的前提之下才能成立.

如果您是 Perl 或是 Python 的使用者, 那麼恭喜您, 因為 Ruby 也同樣完整提供了正規表示法 ( Regular Expression ) 的支援, 並且使用上更加容易. C 的使用者也可以享受 Ruby 特有的內嵌功能, 讓共享變數以及方法更加容易, 可以更快達成目標.

不過, 在此不建議沒有任何程式設計基礎的學習這套語言, 正因為 Ruby 過於物件化, 以至於常讓沒有 OO 甚至程式基礎的人裹足不前, 而在 Ruby 之中的變數 ( Variables ) 觀念也常常會有誤解, 所以如果您沒有任何的程式基礎, 希望您可以學一點點 C++, 至少學到參考 ( Reference ) 的概念, 才能了解 Ruby 的內部真正的運作方式. 在寫程式遇到錯誤時也能夠加快偵錯 ( Debug ) 的腳步

2018/07/05 S18 Web基本原理與技術補充文件(許孟傑):https://hackmd.io/s/SympGICkX

四海之內皆物件

如果您擁有程式設計的基礎, 那麼事不宜遲, 我們馬上來介紹 Ruby 對最大特色 :" Everything's an object! " 字串本身是個物件, 數字本身是個物件, 連正規表示法本身也是個物件.

 

"polarpolar".size >> 10
123.integer? >> TRUE
/(.)(.)(.)/.match("abc")[2] >> "b"

 

Ruby 沿襲了近代 OO 語言的最大特點: 無法多重繼承. 此一規範包括了 Java 和 ObjC 都遵循了, 這是確保物件導向更加嚴謹的設計, 以避免多個被繼承的物件有相同的方法或是屬性而造成衝突, 這就像是一個小孩可以有好多個養父, 卻只會有一個親生父親是一樣的道理. 關於這點在此不贅述, 只要記得「一個物件只能夠選擇繼承一個物件」這樣的單一性即可.

當然「四海之內皆物件」這句話也不是絕對的, 在 Ruby 之中, 沒辦法稱上物件的就是變數本身了. 這是因為 Ruby 的變數不像 C 一樣有個固定的型態, 而是同近年來蓬勃發展的命令稿語言 ( Script Language ) 所採用的參考 ( Reference ) 法, 也就是說:

 

myname = "polarpolar" >> "polarpolar"
mycopyname = myname >> "polarpolar"
myname[0] = "o" >> "o"
myname >> "oolarpolar"
mycopyname >> "oolarpolar"

 

Ruby的特點: 

  1. Ruby 換行不需要分號 ( ; )
  2. Ruby 的迴圈也是使用物件的方法呼叫的
  3. Ruby 的輸出使用 "p" 陳述式, 可節省很多時間

 

1. MVC (RoR的基本架構)和Active Record

 

Model-View-Controller模式的縮寫

(1)Model(處理和資料庫之間的溝通)

由RDBMS所組成的,用Active Record模式來處理

 

(2)View(產生使用者介面)

用HTML/XML/JavaScript來表現

使用者透過View的頁面發出要求

 

 

(3)Controller(處理使用者的要求)

更新Model(進行資料庫的存取)然後由View根據結果將頁面展現出來

如此一來資料的處理和使用者介面便不會互相干擾,因此程式較容易撰寫也較容易維護 

 

(4)Active Record(資料庫的處理)

 Active Record主要是用到它的原則之一 "慣例取代設定"

例如你的程式中有一個名為content的class,Active Record 的慣例

就是會將這個class對應到資料庫中名為contects 的table

所以你並不需要再額外設定RoR要用到什麼名字的table

而且Active Record的英文能力夠強,對於不規則的複數形式變化也能輕鬆應付

 

2. Ruby 

 

 

要使用Ruby,首先要先下載安裝檔 

 

(此說明由陳彥名編輯)

http://rubyforge.org/frs/download.php/47082/ruby186-27_rc2.exe 

下載這個最新版的整合套件,安裝即可。 

要啟用互動式 Ruby Console (Command Line),在命令提示字元中鍵入 irb 按 enter 即可;或是在程式集中尋找 ruby-[版本代號] -> irb - Interactive Ruby Console,在裡面就可以練習 Ruby 的語法,Ruby Console 也會給予回應! 

習慣圖形介面的使用者可以開啟 fxri - Interactive Ruby Help & Console,除了下方的 irb 之外,左邊還有指令說明可供參考。 

關於說明文件,整合套件附的是 Programming Ruby ( 在 Ruby Documentation 資料夾中)

在此提供一本Ruby的教學用書<THE BOOK OF RUBY> 是附在另外一個單獨的安裝套件 RubyInstaller (http://rubyinstaller.org/)

這個連結是有包括書本範例的原始碼 

http://www.sapphiresteel.com/IMG/zip/book-of-ruby.zip

 

 --------------------------------------------------------------------------------------------

 

以下將詳細說明從下載到安裝執行

(此部分由戴瑀葑編輯)

該連結是在Notepad++執行Ruby的教學網頁

http://m3rlinez.blogspot.com/2008/10/compile-source-and-run-programs-from.html

 

圖片來源 

 

下載安裝檔完後執行它

安裝時記得勾第二、三個選項,第三個選項是它會幫你設定環境變數(不然之後要自己去設定)

接下來介紹irb的環境,也就是直譯器

你輸入什麼指令,它會立刻回應你,個人認為是個練習寫語法的好地方

接下來是fxri,是圖形介面的irb,它的好處是有類似JAVA的API功能

接下來教大家從Notepad++來執行Ruby

把「cmd /K ruby "$(FULL_CURRENT_PATH)"」貼上去按儲存

設定名稱和快捷鍵

這樣以後在Notepad++按F6效果等同於在cmd介面執行「ruby 檔案名稱」

即使是JAVA的「javac」和「java」指令也可以設定

 

 

--------------------------------------------------------------------------------------------

 

接下來說明字串輸出和註解方式 

(此部分由戴瑀葑編輯)

 

首先我們來說明一下如何印出字串 

 

在JAVA中,我們要印出字串,需要這樣子做...

 

        System.out.print("hello JAVA");

 

然而在Ruby中,你僅僅只要這樣子就可以了 

 

        print'hello Ruby'

 

很簡單很方便,它與JAVA的差別在於它使用單引號或是雙引號都可以,也不需要用小括弧,而且最後也不需要加分號 

 

這樣的語法在使用上就是將字串print出來但是不換行 

 

如果將字串印出來並換行,相信大家有用JAVA都很熟悉 

 

        System.out.println("hello JAVA");

 

在Ruby這個程式語言,印出字串並換行是使用puts的語法 

 

        puts'hello Ruby'

 

「在Ruby,不管有沒有加小括弧或是使用單、雙引號,在印出字串的效果都是一樣的」 

 

以下是程式在執行時的一些過程 

 

irb(main):001:0> puts'hello Ruby'#這沒有加小括弧 

hello Ruby

=> nil   (補充:這是指結束的意思)

irb(main):002:0> puts('hello Ruby')#有加小括弧 

hello Ruby

=> nil

irb(main):003:0> puts"hello Ruby"#使用雙引號 

hello Ruby

=> nil

irb(main):004:0> puts("hello Ruby")#加小括弧且使用雙引號 

hello Ruby

=> nil

irb(main):005:0> print'hello mei'#用print也是一樣 

hello mei=> nil (補充:因為沒有換行,所以在該行結束)

irb(main):006:0> print"hello mei"

hello mei=> nil

irb(main):007:0> print('hello mei')

hello mei=> nil

irb(main):008:0> print("hello mei")

hello mei=> nil

 

 

相信大家在上面有看到「#」,後面有加註解的詞語 

在使用JAVA時,在程式碼中,適當的註解可以使閱讀的人迅速的了解該程式碼的概念架構和如何執行等等 

 

JAVA做單行註解的方式是使用雙斜線,該行雙斜線後面的字全部視為註解。例如...

 

        //這是JAVA單行註解的方式 

 

「而在Ruby中,是使用「#」作為單行註解的方式,其效果等同於JAVA的雙斜線」 

 

        #這是Ruby單行註解的方式 

         puts"在後面作註解"#也可以這樣註解喔~~JAVA的雙斜線是一樣的 

 

接下來是區域註解。在JAVA中,以斜線加米字號---「/*」作為區域註解的開頭;最後以米字號加斜線---「*/」作為區域註解的結束。例如...

 

        /*  JAVA作區域註解的方式 

            就是這個樣子   */

 

在Ruby中,使用「=begin」作為開頭,以「=end」作為結束。(個人覺得JAVA作區域註解的方式比較方便~~)

 

        =begin   這就是Ruby

        做區域註解的方式 

        就是這麼簡單 

        =end

 

然而Ruby做區域註解,有個地方和JAVA不同。那就是Ruby使用「=begin」必須要在該行一開始時就輸入,「=end」也是 

 

JAVA使用區域註解時是這樣子的。例如...

 

        int number = 10; /* 接下來 

        要開始 

        區域註解 

        結束*/  double PI = 3.1415926;

 

但是在Ruby是不允許這樣做的...

 

        puts'123' =begin

        要開始區域註解囉 

        註解註解我想結束了...  =end  print'123'

 

Ruby區域註解的注意事項: 

 

1.區域註解的該行開頭必須是「=begin」 

2.註解結束那一行的開頭也必須是「=end」 

3.與JAVA不同的地方是,JAVA的區域註解就好像是要把你想註解的地方「包住」;但是Ruby則是告訴interpreter(直譯器)哪幾行是註解 

 

 

例如: 

 

puts("ABC")

print'要開始註解了'

=begin 註解註解..........

然後......我想結束了 

=end  很不幸的我還是註解 

puts"註解已經結束了"

 

「簡單說就是告訴interpreter「第三行」到「第五行」是註解,叫interpreter不要執行第三、四、五行。」 

 

 

--------------------------------------------------------------------------------------------

 

接下來是判斷式的說明

(此部分由邱弘承編輯)

 

[IF..THEN..ELSE]條件判斷式 

 

Conditional Statement 在Ruby裡其實跟python很像 

和Java不同的是 他們都不用 { } 來標示開始和結束 

而(Ruby)是用"換行" "then" 和 ":" 來表示開始 "{"

用"end"來表示結束 "}"

 

以下我們用範例來說明:

1. if x == 1 then puts( 'ok' ) end # with 'then'

2. if x == 1 : puts( 'ok' ) end # with colon

3. if x == 1 puts( 'ok' ) end # syntax error !

 

這個範例說明了 then 和 : 的是用時機是在不想換行的時候 

不用的話就會出現錯誤 

如果把第三個改成 

if x == 1 

puts( 'ok' )

end

這樣的話就不會出現錯誤了 

而end是要在每個Statements結束一定都要打的 

 

 

 

[AND..OR..NOT]布林運算式 

 

and or not 這些運算式其實都跟其它的程式語言一樣 

都是 "&&"、 "||"、 "!" 可是比較特別的是 

Ruby它可以直接用英文來表示,也就是可以寫成 "and" "or" 和 "not"

 

可是看似相同的語法其實暗藏懸機 

用英文和用符號表示 這兩個是有差的 

其實在Ruby中符號的優先權是比文字高的!!

也就是在沒有使用括號表示先後順序時 會先作 "&&" 和 "||" 再作"and" "or"

 

看個範例就懂了:

1.

if ( 1==3 ) and (2==1) || (3==3) then

puts('true')

else puts('false')

end

這個output會是甚麼呢? 答案是 false

因為在沒有括號標示優先順序時

他會先做 (2==1) || (3==3) 再 and ( 1==3 )

所以(2==1) || (3==3) --> ture ; ( 1==3 ) --> false 兩個作and之後 就是false

所以會執行 puts('false')  答案是false!!!

 

 

可是如果把它改成

if (( 1==3 ) and (2==1)) || (3==3) then

puts('true')

else puts('false')

end

答案就完全相反啦!!!!

 

--------------------------------------------------------------------------------------------

 

接下來是Array和Hash的簡單介紹

(此部分由郭詠欣編輯)

 

 

Array

 

先創造一個array 名取為a方法有 

a = [ 'a' , 'b' , 'c' , [3,4,5] ] 

或 

a = Array.new(['a' , 'b' , 'c' , [3,4,5]]) 

如果要印出a的第3個 則打 

print  a[3]   

印出 

345    

如要印出整個a 則直接打 

print  a  

印出 

abc345 

而當如果打 

print a.inspect 

則結果會為 

["a", "b", "c", [3, 4, 5]] 

  

  

而當你想創造一個空的array則打 

a = Array.new 

而當想創創造array內有兩個空的位置則 

a = Array.new(2) 

而如果你打 

a = Array.new(3,"hello world") 

則代表在重複3次"hello world"存進array 

puts(a.inspect)印出為 

["hello world", "hello world"] 

  

而我們也可以用非一般的方法創造出array

例如

arr = %w(1 2 3 4 5 6 a)

那則會存進

["1", "2", "3", "4", "5", "6", "a"]

以空格切開

 

之後看到array裡的位置

a= ['h','e','l','l','o',' ','w','o','r','l','d']為例

如果打

a[2,5]則代表由第2個位置開始的5個

所以如果印出,結果為下

llo w

但如果是arr[0..4]則是代表由0的位置到第4個位置

所以如果印出,結果為下

hello

裡面的位置也可能有為負

如有為負則代表從最後開始算

像如印出arr[-5..-1] ,結果為下

world

 

而array的指定問題

當我們指定

array2= array1

則當我們改變array1則array2也會改變

但當我們打

arr3=arr1.clone

那即使改變array1,array3也不會改變

 

 

而之後array的一些較常用方法有: 

先假設 

a=[1,2,3,4]

b=[4,5,6]

self & array回傳兩陣列的交集 

p a & b     

結果為[4] 

self | array回傳兩陣列的並集 

p a | b       

結果為[1,2,3,4,5,6] 

self + array回傳兩陣列的連集 

p a + b    

結果為[1,2,3,4,4,5,6]

self << array向陣列追加一值,傳回自身 

a << b

p a 

結果為[1, 2, 3, 4, [4, 5, 6]]

self <=> array:兩陣列值的比較,回傳結果為1,0,-1 

p a <=> b  

結果為-1,因為其第0個b的值4即比a的值1大

如值一樣大則看下一個,如到最後都一樣則傳回0,但如果其陣列為字串,則以ASCII 來比較

self.length傳回陣列的長度 

p a.length

結果為4 

self.clear清空陣列 

p a.clear    

結果為[]

self.reverse將陣列反轉,產生新陣列傳回 

p a.reverse     

結果為[4, 3, 2, 1]

self.reverse!將陣列反轉,傳回自身 

self.sort將陣列排序,產生新陣列傳回 

a=[4, 3, 2, 1]

p a.sort 

結果為[1, 2, 3, 4] ,但如果其陣列為字串,則會產生錯誤

self.sort!將陣列排序,傳回自身 

self.to_s將陣列導出轉成字串 

p a.to_s     

結果為"1234"

 

 

 

Hash

 

Hash是鍵到值的對印關係,可以看作是使用非數字索引的陣列(可以使用任意的鍵來索引,字串、數字等等的)

 

創造一個hash

h1 = Hash.new

h2 = Hash.new("Some kind of ring")

如回傳的值未存在則h1會回傳nil而h2會回傳"Some kind of ring"

 

 

而指定鍵與值的方法有3種 

一種為透過大括號{}及=>來定義,就像鍵=>,但如沒有箭頭他則會如{鍵,值,鍵,值…….}定義,如下 

h3 = {

'one'=>'mouse',

'two'=>'cattle ',

'three'=>'tiger',

'four'=>'rabbit'

}

或在[]內定義與大括號類似,如沒有=>,他會按照順序以[鍵,值,鍵,值…….] ,如下

h4=Hash[1,’a’,2,’b’]

而你也可以一個一個定義,如下

h5[‘1’]=’a’

h5[‘2’]=’b’

 

 

由於鍵的型態可以為字串或數字,所以要小心區分,如下

h4=Hash[1, ’a’ , ’2’, ’b’]

如印出h4[1]結果為下

‘a’

但如印出h4[2] 結果為

nil

因其一個字串一個是數字,因此 2 與 '2' 是不同的

 

  

 而hash的一些常用方法有: 

self == hash查看其詞典是否相同,傳回true或false 

self.invert將表裡的鍵與值顛倒,鍵變值,值變鍵

self.default讀取表的預設取值,如找不到則傳回該預設值

self.clear將表清空 

self.empty?查看表是否為空,傳回true或false 

self.key?(i)能否找到鍵為i的的資料,傳回true或false 

self.value?(i)能否找到值為i的的資料,傳回true或false

  

--------------------------------------------------------------------------------------------

 

接下來是簡單介紹迴圈的部分

(此部分由陳建文編輯)

 

 

能夠直接將每個個所需要的數字直接的印出來, 

就用.each   

  

範例:
[1,2,3].each  do |i|      #.each 是將每個數字印出
      puts( i )
end 

  

顯示的結果為:
1
2

  

在這邊所使用到的do...end 

在RUBY當中能用 {大掛號} 就能夠輕鬆取代了 

這樣的改變不會影響到顯示出來的結果的 

  

也能夠使用in將.each功能取代 

for s in [1,2,3] do 
     puts( s )
end 

  

甚至只需要輸入數字的頭與尾就能夠將全部的數字顯示了

此時需要用到.collect

 

範例:

x = (1..10).collect{ |i| i }
p( x )

 

顯示的結果為:

[1, 2, 3, 4, 5, 6, 7, 8, 9 ,10]

 

最方便的就是能夠馬上找出一連串數字中得最大值與最小值,

不像JAVA必須要出入一連串的指令後經過比較後才有辦法找到

 

範例:

arr = [1,2,3,4,5]

p( arr.min )     #找到最小值
p( arr.max )     #找到最大值

 

結果當然就馬上顯示出你所需要的答案拉!!!
1
5

 

接下來說明一下RUBY的迴圈 

 

範例:

 

$hours_asleep = 0

         def tired
     if $hours_asleep >= 8 then
          $hours_asleep = 0
          return false
      else
            $hours_asleep += 1 
            return true 
      end
end

 

def snore
puts('snore....')
end

 

 

def sleep
puts("z" * $hours_asleep )
end

 

這會造成這種的效果:

z
zz
zzz
zzzz
zzzzz
zzzzzz
zzzzzzz
zzzzzzzz

 

以下有3總方式皆能表現出這種效果

 

1.

while tired do sleep end

2.

while tired
sleep
end

3.

sleep while tired

 

如果輸入這總方式的話

begin
sleep
snore
end while tired

 

能夠產成這種效果

snore....
z
snore....
zz
snore....
zzz
snore....
zzzz
snore....
zzzzz
snore....
zzzzzz
snore....
zzzzzzz
snore....
zzzzzzzz
snore....

 

還有如果有需要換行的話在puts(裡面這用\n)\,

後面直接繼續接所要印出的內容,

這樣就能夠換行了,

範例
puts( "\n讓我ALL PASS" )

以上由戴瑀葑進行資料統整

 

Class使用

class Person
@@num_person = 0 #Attribute
def initialize(data)
@@num_person += 1
end
end

p = Person.new(1) #建立新物件

#toString的定義方法(印出字串的方法放進此物件的時候用)
def to_s
return "string"
end

3. Rail Framework
隨著應用資料庫網頁的發展,需要更方便的管理系統,所以因應而生。
主要是建立在MVC架構上
分為應用資料,圖形表示元素與輸入進程邏輯,以下列三種表示
ActiveRecordis 用來把 database table 定位成一個物件
ActionViewis 一套用來修改使用者介面的便利方法
ActionControlleris 一套可以輕鬆控制的方法

4. ActionController, ACtionView
ruby and rail 有ActionController和ACtionView 兩個class,他們彼此合作來服務客戶端以及產生視覺效果
要使用rails的controller的時候,可以透過鍵入ruby script/generate controller的名字來開啟內建的Controller generator
ruby on rails 應用必須運行在網頁伺服器上
內建有一個叫做Mongrel的網頁伺服器可以讓管理者簡單的在本地端測試rails程式
當輸出的時候會產生鑲嵌有ruby的XHTML副檔名會變成rhtml
request物件會包含環境變數和網頁的資訊
鑲嵌ruby在XHTML裡的程式碼在<%=和%>標籤中間的時候代表文字,沒在裡面則代表執行碼
rails使用headers和footers來排版
排版的時候可以使用yield來產生特定方法的模板

 

 

 

 

 

5. DB driven Web application
Rail將定位資料庫成為應用物件的Object-Relational Mapping (ORM)精神發揮到極致
Rails的物件能夠用來壓縮從ActiveRecord繼承到的資料庫
ActiveRecord的其一應用是使得能夠經由ActiveRecord::Base來表示每個資料庫裡的table
規定用小寫的名字來表示table裡的多個model
在Ruby console鍵入ruby script/generate model employee後可開啟Employee model

ActiveRecordobject裡的Migration可以讓你用Rails操作資料庫
Rails的CRUD是指ActiveRecord內建的Create, Retrieve, Update 和 Destroy方法
我們可以藉由輸入rake db:migrate使用Ruby’s rakecommand來執行migration,讓他能呼叫所有位於db/migrate 目錄下的self.upmethod
可以鍵入rake db:migrate VERSION=0呼叫每個migration的self.down方法來捲回migrations
scaffold是能自動創建CRUD要素的方法,像是new,edit和list。

 

什麼是Ruby? 什麼是Ruby On Rails (ROR)?

簡單來說,Ruby是一種直譯式的物件導向語言,1993年由日本人松本行弘開發,1995年釋出。Ruby是由Perl演變而來,語法比Perl更為簡潔,並具備完整的物件導向能力,內建的正規表達式引擎,在處理文字上有相當優異的表現。

RoR是用Ruby寫的網頁應用程式開發框架(web application framework)是由David Heinemeier Hansson(簡稱 DHH)所開發的一個架構,目標主要是在加快網站(用資料庫驅動)的開發速度與簡化開發中的過程,它有兩個重大的原則:一個是絕不做重覆的事,(Don’t Repeat Yourself),程式設計師要寫的程式碼當然愈少愈好,因為程式碼少的話,改起來比較容易而且出錯的機率也會降低許多;另一個原則是用慣例(通則)取代設定。總而言之它能輕鬆快速地開發Web 2.0網站及Ajax,使用MVC架構,將程式碼、網頁模板及資料庫加以分離,開發網站的速度相當驚人。