Other data structures
Arrays and ranges
陣列(arrays)是具有一組特定順序的元素集合。陣列的索引值從 0 開始。
split
使用 split 方法,將字串轉成陣列:
"foo bar baz".split
=> ["foo", "bar", "baz"]
split 預設是使用空白隔開元素,你也可以自訂任何元素:
"fooxbarxbazx".split("x")
=> ["foo", "bar", "baz"]
取出元素
可以使用 [] 來取出元素:
a = [45,67,89]
a[0] => 45
a[-1] => 89
也可以使用 Ruby 提供的別名來取出元素:
a = [45,67,89]
a.first => 45
a.second => 67
a.last => 89
a.last == a[-1]
=> true
基本的運算子操作
a = [45,67,89]
x = a.length
x == 3 => true
x == 1 => false
x != 1 => true
x >= 1 => true
x < 1 => false
陣列其他方法
empty?、include?、sort、reverse、shuffle
a = [45,8,79]
a.empty? => false
a.include?(45) => true
a.sort => [8,45,79]
a.reverse => [79,45,8]
a.shuffle => [8,79,45]
a => [45,8,79]
上面的寫法都不會改變陣列 a 原本的值,如果要修改值,可以使用 !(讀作 bang)
a = [45,8,79]
a.sort! => [8,45,79]
a => [8,45,79]
增加元素
如果要增加陣列元素,可以用 push 或 <<:
a = [45,8,79]
a.push(6) => [45,8,79,6]
a << "foo" => [45,8,79,6,"foo"]
a << "bar" << 9 => [45,8,79,6,"foo","bar",9] # 可以串接
join
跟 split 相反,join 是把陣列元素轉成字串,可以自訂區隔的元素:
a = [45,8,79,6,"foo","bar",9]
a.join => "458796foobar9"
a.join(", ") => "45, 8, 79, 6, foo, bar, 9"
range
0..9 => 0..9
0..9.to_a # 發生錯誤
=> NoMethodError: undefined method `to_a' for 9:Fixnum
(0..9).to_a # 要用 () 包起來
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
range 用來取出陣列中的一組元素:
a = %w[foo bar baz quux] # %w 建立一個元素為字串的陣列
=> ["foo", "bar", "baz", "quux"]
a[0..2]
=> ["foo", "bar", "baz"]
技巧:range 的結尾用 -1 時,就算不知道陣列的長度,也能從起始值開始一直到獲取最後一個元素:
a = (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a[2..(a.length-1)] # 利用 length-1 取得最後一個元素的索引值
=> [2, 3, 4, 5, 6, 7, 8, 9]
a[2..-1] # 使用 -1
=> [2, 3, 4, 5, 6, 7, 8, 9]
range 也可以用在字母上:
('a'..'e').to_a
=> ["a", "b", "c", "d", "e"]
Blocks
block 可以用 {},通常是單行呈現會使用:
(1..5).each { |i| puts 2 * i }
=> 2
=> 4
=> 6
=> 8
=> 10
也可以用 do...end,通常是多行:
(1..5).each do |i|
puts 2 * i
end
Hashes and symbols
Hashes 本質上就是一種陣列,不過它的索引值不侷限用數字:
user = {} # Hash 的字面值,{} 代表一個空的 Hash
user["first_name"] = "Luffy" # 設定 key 為 first_name,value 為 Luffy
user["last_name"] = "Wang" # 設定 key 為 last_name,value 為 Wang
user["first_name"]
=> "Luffy"
user
=> {"first_name" => "Luffy", "last_name" => "Wang"}
symbol 可以被當成 Hash 的 key 來使用:
user = { :name => "Luffy Wang", :email => "[email protected]"}
user[:name]
=> "Luffy Wang"
user[:address]
=> nil # 如果找不到 key 對應的 value,會丟出 nil
後來改得更簡約,把 => 改成 :
user = { name: "Luffy Wang", email: "[email protected]" }
用 symbol 的好處是:
- 它不能被隨意更改,也就是在建立的時候,就不能再改變了
- 它是唯一的,所以節省記憶體
注意 symbol 的命名不能用 -,這是無效的,會丟出錯誤訊息。
巢狀 Hash:
params = {}
params[:user] = { name: "Luffy wang", email: "luffy@example" }
params
=> { user: { name: "Luffy wang", email: "luffy@example" } }
params[:user][:name]
=> "Luffy wang"
Hash 的迭代方法:
flash = { success: "It worked!", danger: "It failed." }
flash.each do |key, value|
puts "Key #{key.inspect} has value #{value.inspect}"
end
=> Key :success has value "It worked!"
=> Key :danger has value "It failed."
inspect 方法會輸出物件的字面值,例如:
puts (1..5).to_a
=> 1
=> 2
=> 3
=> 4
=> 5
puts (1..5).to_a.inspect
=> [1,2,3,4,5]
puts :name, :name.inspect
=> name
=> :name
puts "It worked!", "It worked!".inspect
=> It worked!
=> "It worked!"
快速輸出 inspect:
p :name # 等於 puts :name.inspect
=> :name
CSS revisited
現在來看一下在 application.html.erb 裡面的這行:
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track' => true
其中,調用函數的時候,() 可以省略,所以下面這兩行意思一樣:
stylesheet_link_tag('application', media: 'all',
'data-turbolinks-track' => true)
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track' => true
然後,media 的部分是一個 Hash,調用函數時,如果 Hash 是最後一個參數,可以省略 {},所以下面兩行是一樣的意思:
stylesheet_link_tag 'application', { media: 'all',
'data-turbolinks-track' => true }
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track' => true
還有,data-turbolinks-track 這個 key 使用了舊的寫法 =>,是因為 symbol 不能使用 -。
最後,Ruby 不在乎你換行。
總結一下,這行給的訊息:
stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track' => true
- 調用了一個
stylesheet_link_tag函數 - 傳入兩個參數,一個是字串
application,指定 CSS 的路徑;一個是 Hash ,包含兩個元素,第一個指定媒體類型,第二個啟動 Rails 4.0 新增的 Turbolink - 因為使用
<%= %>,函數的執行結果會透過 ERb 置入 tamplate 中
如果在 CSS 檔名後面看到額外的字串,例如 ?body=1,這是 Rails 加上的,確保修改完 CSS 後,瀏覽器會重新載入。