日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第四章 Rails 背后的 Ruby

發(fā)布時間:2024/5/17 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第四章 Rails 背后的 Ruby 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第四章 Rails 背后的 Ruby

有了第三章中的例子做鋪墊,本章將為你介紹一些對 Rails 來說很重要的 Ruby 知識。Ruby 語言的知識點很多,不過對一個 Rails 開發(fā)者而言需要掌握的很少。我們采用的是有別于常規(guī)的 Ruby 學習過程,我們的目標是開發(fā)動態(tài)的 Web 應用程序,所以我建議你先學習 Rails,在這個過程中學習一些 Ruby 知識。如果要成為一個 Rails 專家,你就要更深入的掌握 Ruby 了。本書會為你在成為專家的路途上奠定一個堅實的基礎。如?1.1.1 節(jié)中說過的,讀完本書后我建議你閱讀一本專門針對 Ruby 的書,例如《Ruby 入門》、《The Well-Grounded Rubyist》或《Ruby 之道》。

本章介紹了很多內(nèi)容,第一遍閱讀沒有掌握全部是可以理解的。在后續(xù)的章節(jié)我會經(jīng)常提到本章的內(nèi)容。

4.1 導言

從上一章我們可以看到,即使不懂任何背后用到的 Ruby 語言,我們也可以創(chuàng)建一個 Rails 應用程序骨架,也可以進行測試。不過我們依賴的是本教程中提供的測試代碼,得到錯誤信息,然后讓其通過。我們不能總是這樣做,所以這一章我們要暫別網(wǎng)站開發(fā)學習,正視我們的 Ruby 短肋。

上次接觸應用程序時,我們已經(jīng)使用 Rails 布局去掉了幾乎是靜態(tài)的頁面中的代碼重復。(參見代碼 4.1)

代碼 4.1?示例程序的網(wǎng)站布局?
app/views/layouts/application.html.erb

<!DOCTYPE html> <html> <head> <title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title> <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> </head> <body> <%= yield %> </body> </html>

讓我們把注意力集中在代碼 4.1 中的這一行:

<%= stylesheet_link_tag "application", :media => "all" %>

這行代碼使用 Rails 內(nèi)置的方法?stylesheet_link_tag(更多內(nèi)容請查看?Rails API 文檔)為所有的媒介類型引入了?application.css。對于經(jīng)驗豐富的 Rails 開發(fā)者來說,這一行很簡單,但是這里卻至少包含了困惑著你的四個 Ruby 知識點:內(nèi)置的 Rails 方法,不用括號的方法調(diào)用,Symbol 和 Hash。這幾點本章都會介紹。

除了提供很多內(nèi)置的方法供我們在視圖中使用之外,Rails 還允許我們自行創(chuàng)建。自行創(chuàng)建的這些方法叫做幫助方法(helper)。要說明如何自行創(chuàng)建一個幫助方法,我們要來看看代碼 4.1 中標題那一行:

Ruby on Rails Tutorial Sample App | <%= yield(:title) %>

這行代碼依賴于每個視圖中定義的頁面標題(使用?provide),例如

<% provide(:title, 'Home') %> <h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a> sample application. </p>

那么如果我們不提供標題會怎樣呢?我們的標題一般都包含一個公共部分,如果想更具體些就要加上一個變動的部分了。我們在布局中用了個小技巧,基本上已經(jīng)實現(xiàn)了這樣的標題。如果我們刪除視圖中的?provide?方法調(diào)用,輸出的標題就沒有了變動的那部分:

Ruby on Rails Tutorial Sample App |

公共部分已經(jīng)輸出了,而且后面還有一個豎杠?|。

為了解決這個標題問題,我們會自定義一個幫助方法,叫做?full_title。如果視圖中沒有定義標題,full_title?會返回標題的公共部分,即“Ruby on Rails Tutorial Sample App”;如果定義了,則會在公共部分后面加上一個豎杠,然后再接上該頁面的標題(如代碼 4.2)。1

代碼 4.2?定義?full_title?幫助方法?
app/helpers/application_helper.rb

module ApplicationHelper# Returns the full title on a per-page basis.def full_title(page_title)base_title = "Ruby on Rails Tutorial Sample App"if page_title.empty?base_titleelse"#{base_title} | #{page_title}"endend end

現(xiàn)在我們已經(jīng)定義了一個幫助方法,我們可以用它來簡化布局,將

<title>Ruby on Rails Tutorial Sample App | <%= yield(:title) %></title>

替換成

<title><%= full_title(yield(:title)) %></title>

如代碼 4.3 所示。

代碼 4.3?示例程序的網(wǎng)站布局?
app/views/layouts/application.html.erb

<!DOCTYPE html> <html> <head> <title><%= full_title(yield(:title)) %></title> <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> </head> <body> <%= yield %> </body> </html>

為了讓這個幫助方法起作用,我們要在“首頁”視圖中將不必要的“Home”這個詞刪掉,讓標題只保留公共部分。首先我們要按照代碼 4.4 的內(nèi)容更新現(xiàn)有的測試,增加對沒包含?'Home'?的標題測試。

代碼 4.4?更新“首頁”標題的測試?
spec/requests/static_pages_spec.rb

require 'spec_helper'describe "Static pages" dodescribe "Home page" doit "should have the h1 'Sample App'" dovisit '/static_pages/home'page.should have_selector('h1', :text => 'Sample App')endit "should have the base title" dovisit '/static_pages/home'page.should have_selector('title',:text => "Ruby on Rails Tutorial Sample App")endit "should not have a custom page title" dovisit '/static_pages/home'page.should_not have_selector('title', :text => '| Home')endend... end

試試看你能否猜到為什么我們添加了一個新測試而不是直接修改之前的測試。(提示:答案在?3.3.1 節(jié)中。)

運行測試,查看是否有一個測試失敗了:

$ bundle exec rspec spec/requests/static_pages_spec.rb

為了讓測試通過,我們要將“首頁”視圖中的?provide?那行刪除,如代碼 4.5 所示。

代碼 4.5?刪除標題定義后的“首頁”?
app/views/static_pages/home.html.erb

<h1>Sample App</h1> <p> This is the home page for the <a href="http://railstutorial.org/">Ruby on Rails Tutorial</a> sample application. </p>

現(xiàn)在測試應該可以通過了:

$ bundle exec rspec spec/requests/static_pages_spec.rb

和引入應用程序樣式表那行代碼一樣,代碼 4.2 的內(nèi)容對經(jīng)驗豐富的 Rails 開發(fā)者來說看起來很簡單,但是充滿了很多會讓人困惑的 Ruby 知識:module,注釋,局部變量的賦值,布爾值,流程控制,字符串插值,還有返回值。這章也會介紹這些知識。

4.2 字符串和方法

學習 Ruby 我們主要使用的工具是 Rails 控制臺,它是用來和 Rails 應用程序交互的命令行,在?2.3.3 節(jié)中介紹過。這個控制臺是基于 Ruby 的交互程序(irb)開發(fā)的,因此也就能使用 Ruby 語言的全部功能。(在?4.4.4 節(jié)中會介紹,控制臺還可以進入 Rails 環(huán)境。)使用下面的方法在命令行中啟動控制臺:

$ rails console Loading development environment >>

默認情況下,控制臺是以開發(fā)環(huán)境啟用的,這是 Rails 定義的三個獨立的環(huán)境之一(其他兩個是測試環(huán)境和生產(chǎn)環(huán)境)。三個環(huán)境的區(qū)別在本章還不需要知道,我們會在?7.1.1 節(jié)中更詳細的介紹。

控制臺是個很好的學習工具,你不用有所畏懼盡情的使用吧,沒必要擔心,你(幾乎)不會破壞任何東西。如果你在控制器中遇到問題了可以使用 Ctrl-C 結(jié)束當前執(zhí)行的命令,或者使用 Ctrl-D 直接退出控制臺。在閱讀本章后面的內(nèi)容時,你會發(fā)現(xiàn)查閱?Ruby API?會很有用。API 包含很多信息,例如,如果你想查看關于 Ruby 字符串更多的內(nèi)容,可以查看其中的?String類頁面。

4.2.1 注釋

Ruby 中的注釋以井號?#(也叫“Hask Mark”,或者更詩意的叫“散列字元”)開頭,一直到行尾結(jié)束。Ruby 會忽略注釋,但是注釋對代碼閱讀者(包括代碼的創(chuàng)作者)卻很有用。在下面的代碼中

# Returns the full title on a per-page basis.def full_title(page_title)...end

第一行就是注釋,說明了后面方法的作用。

一般無需在控制臺中寫注釋,不過為了說明代碼,我會按照下面的形式加上注釋,例如:

$ rails console >> 17 + 42 # Integer addition => 59

在本節(jié)的閱讀過程中,在控制臺中輸入或者復制粘貼命令時,如果愿意你可以不復制注釋,反正控制臺會忽略注釋。

4.2.2 字符串

字符串算是 Web 應用程序中最有用的數(shù)據(jù)結(jié)構(gòu)了,因為網(wǎng)頁的內(nèi)容就是從數(shù)據(jù)庫發(fā)送到瀏覽器的字符串。我們先在控制臺中體驗一下字符串,這次我們使用?rails c?啟動控制臺,這是?rails console?的簡寫形式:

$ rails c >> "" # 空字符串 => "" >> "foo" # 非空的字符串 => "foo"

上面的字符串是字面量(字面量字符串,literal string),通過雙引號(")創(chuàng)建。控制器回顯的是每一行的計算結(jié)果,本例中字符串字面量的結(jié)果就是字符串本身。

我們還可以使用?+?號連接字符串:

>> "foo" + "bar" # 字符串連接 => "foobar"

"foo"?連接?"bar"?的運行結(jié)果是字符串?"foobar"。2

另外一種創(chuàng)建字符串的方式是通過一個特殊的句法(#{})進行插值操作:3

>> first_name = "Michael" # 變量賦值 => "Michael" >> "#{first_name} Hartl" # 字符串插值 => "Michael Hartl"

我們先把“Michael”賦值給變量?first_name,然后將其插入到字符串?"#{first_name} Hartl"?中。我們可以將兩個字符串都賦值給變量:

>> first_name = "Michael" => "Michael" >> last_name = "Hartl" => "Hartl" >> first_name + " " + last_name # 字符串連接,中間加了空格 => "Michael Hartl" >> "#{first_name} #{last_name}" # 作用相同的插值 => "Michael Hartl"

注意,兩個表達式的結(jié)果是相同的,不過我傾向使用插值的方式。在兩個字符串中加入一個空格(" ")顯得很別扭。

打印字符串

打印字符串最常用的 Ruby 方法是?puts(讀作“put ess”,意思是“打印字符串”):

>> puts "foo" # 打印字符串 foo => nil

puts?方法還有一個副作用(side-effect):puts "foo"?首先會將字符串打印到屏幕上,然后再返回空值字面量:nil?是 Ruby 中的“什么都沒有”。(后續(xù)內(nèi)容中為了行文簡潔我會省略?=> nil。)

puts?方法會自動在輸出的字符串后面加入換行符?\n,功能類似的?print?方法則不會:

>> print "foo" # 打印字符串(和 puts 類似,但沒有添加換行符) foo=> nil >> print "foo\n" # 和 puts "foo" 一樣 => nil

單引號字符串

目前介紹的例子都是使用雙引號創(chuàng)建的字符串,不過 Ruby 也支持用單引號創(chuàng)建字符串。大多數(shù)情況下這兩種字符串的效果是一樣的:

>> 'foo' # 單引號創(chuàng)建的字符串 => "foo" >> 'foo' + 'bar' => "foobar"

不過兩種方法還是有個很重要的區(qū)別:Ruby 不會對單引號字符串進行插值操作:

>> '#{foo} bar' # 單引號字符串不能進行插值操作 => "\#{foo} bar"

注意控制臺是如何使用雙引號返回結(jié)果的,需要使用反斜線轉(zhuǎn)義特殊字符,例如?#。

如果雙引號字符串可以做單引號所做的所有事,而且還能進行插值,那么單引號字符串存在的意義是什么呢?單引號字符串的用處在于它們真的就是字面值,只包含你輸入的字符。例如,反斜線在很多系統(tǒng)中都很特殊,就像換行符(\n)一樣。如果有一個變量需要包含一個反斜線,使用單引號就很簡單:

>> '\n' # 反斜線和 n 字面值 => "\\n"

和前例的?#?字符一樣,Ruby 要使用一個額外的反斜線來轉(zhuǎn)義反斜線,在雙引號字符串中,要表達一個反斜線就要使用兩個反斜線。對簡單的例子來說,這省不了多少事,不過如果有很多需要轉(zhuǎn)義的字符就顯得出它的作用了:

>> 'Newlines (\n) and tabs (\t) both use the backslash character \.' => "Newlines (\\n) and tabs (\\t) both use the backslash character \\."

4.2.3 對象及向其傳遞消息

Ruby 中一切皆對象,包括字符串和?nil?都是。我們會在?4.4.2 節(jié)介紹對象技術(shù)層面上的意義,不過一般很難通過閱讀一本書就理解對象,你要多看一些例子才能建立對對象的感性認識。

不過說出對象的作用就很簡單:它可以響應消息。例如,一個字符串對象可以響應?length?這個消息,它返回字符串包含的字符數(shù)量:

>> "foobar".length # 把 length 消息傳遞給字符串 => 6

這樣傳遞給對象的消息叫做方法,它是在對象中定義的函數(shù)。4?字符串還可以響應?empty??方法:

>> "foobar".empty? => false >> "".empty? => true

注意?empty??方法末尾的問號,這是 Ruby 的一個約定,說明方法的返回值是布爾值:true?或?false。布爾值在流程控制中特別有用:

>> s = "foobar" >> if s.empty? >> "The string is empty" >> else >> "The string is nonempty" >> end => "The string is nonempty"

布爾值還可以使用?&&(和)、||(或)和?!(非)操作符結(jié)合使用:

>> x = "foo" => "foo" >> y = "" => "" >> puts "Both strings are empty" if x.empty? && y.empty? => nil >> puts "One of the strings is empty" if x.empty? || y.empty? "One of the strings is empty" => nil >> puts "x is not empty" if !x.empty? "x is not empty" => nil

因為 Ruby 中的一切都是對象,那么?nil?也是對象,所以它也可以響應方法。舉個例子,to_s?方法基本上可以把任何對象轉(zhuǎn)換成字符串:

>> nil.to_s => ""

結(jié)果顯然是個空字符串,我們可以通過下面的方法串聯(lián)(chain)驗證這一點:

>> nil.empty? NoMethodError: You have a nil object when you didn\'t expect it! You might have expected an instance of Array. The error occurred while evaluating nil.empty? >> nil.to_s.empty? # 消息串聯(lián) => true

我們看到,nil?對象本身無法響應?empty??方法,但是?nil.to_s?可以。

有一個特殊的方法可以測試對象是否為空,你應該能猜到這個方法:

>> "foo".nil? => false >> "".nil? => false >> nil.nil? => true

下面的代碼

puts "x is not empty" if !x.empty?

說明了關鍵詞?if?的另一種用法:你可以編寫一個當且只當?if?后面的表達式為真時才執(zhí)行的語句。對應的,關鍵詞?unless也可以這么用:

>> string = "foobar" >> puts "The string '#{string}' is nonempty." unless string.empty? The string 'foobar' is nonempty. => nil

我們需要注意一下?nil?的特殊性,除了?false?本身之外,所有的 Ruby 對象中它是唯一一個布爾值為“假”的:

>> if nil >> true >> else >> false # nil 是假值 >> end => false

基本上所有其他的 Ruby 對象都是“真”的,包括 0:

>> if 0 >> true # 0(除了 nil 和 false 之外的一切對象)是真值 >> else >> false >> end => true

4.2.4 定義方法

在控制臺中,我們可以像定義?home?動作(代碼 3.6)和?full_title?幫助方法(代碼 4.2)一樣進行方法定義。(在控制臺中定義方法有點麻煩,我們一般會在文件中定義,不過用來演示還行。)例如,我們要定義一個名為?string_message?的方法,可以接受一個參數(shù),返回值取決于參數(shù)是否為空:

>> def string_message(string) >> if string.empty? >> "It's an empty string!" >> else >> "The string is nonempty." >> end >> end => nil >> puts string_message("") It\'s an empty string! >> puts string_message("foobar") The string is nonempty.

注意 Ruby 方法會非顯式的返回值:返回最后一個語句的值。在上面的這個例子中,返回的值會根據(jù)參數(shù)是否為空而返回兩個字符串中的一個。Ruby 也支持顯式的指定返回值,下面的代碼和上面的效果一樣:

>> def string_message(string) >> return "It's an empty string!" if string.empty? >> return "The string is nonempty." >> end

細心的讀者可能會發(fā)現(xiàn)其實這里第二個?return?不是必須的,作為方法的最后一個表達式,不管有沒有?return,字符串?"The string is nonempty."?都會作為返回值。不過兩處都加上?return?看起來更好看。

4.2.5 回顧一下標題的幫助方法

下面我們來理解一下代碼 4.2 中的?full_title?幫助方法:5

module ApplicationHelper# 根據(jù)所在頁面返回完整的標題 # 在文檔中顯示的注釋def full_title(page_title) # 方法定義base_title = "Ruby on Rails Tutorial Sample App" # 變量賦值if page_title.empty? # 布爾測試base_title # 非顯式返回值else"#{base_title} | #{page_title}" # 字符串插值endend end

方法定義、變量賦值、布爾測試、流程控制和字符串插值——組合在一起定義了一個可以在網(wǎng)站布局中使用的幫助方法。還用到了?module ApplicationHelper:module 為我們提供了一種把相關方法組織在一起的方式,稍后我們可以使用?include把它插入其他的類中。編寫一般的 Ruby 程序時,你要自己定義一個 module 然后再顯式的將其引入類中,但是對于幫助方法所在的 module 就交由 Rails 來處理引入了,最終的結(jié)果是?full_title?方法自動的就可以在所有的視圖中使用了。

4.3 其他的數(shù)據(jù)類型

雖然 Web 程序一般都是處理字符串,但也需要其他的數(shù)據(jù)類型來生成字符串。本節(jié)我們就來介紹一些對開發(fā) Rails 應用程序很重要的 Ruby 中的其他數(shù)據(jù)類型。

4.3.1 數(shù)組和 Range

數(shù)組就是一組順序特定的元素。本書尚且沒有用過數(shù)組,不過理解了數(shù)組就能很好的理解 Hash (4.3.3 節(jié)),也有助于理解 Rails 中的數(shù)據(jù)模型(例如?2.3.3 節(jié)中用到的?has_many?關聯(lián),10.1.3 節(jié)會做詳細介紹)。

目前我們已經(jīng)花了很多的時間理解字符串,從字符串過渡到數(shù)組可以從?split?方法開始:

>> "foo bar baz".split # 把字符串分割成有三個元素的數(shù)組 => ["foo", "bar", "baz"]

上述代碼的返回結(jié)果是一個有三個元素的數(shù)組。默認情況下,split?在空格處把字符串分割成數(shù)組,當然你幾乎可以在任何地方進行分割:

>> "fooxbarxbazx".split('x') => ["foo", "bar", "baz"]

和其他編程語言的習慣一樣,Ruby 中數(shù)組的索引(index)也是從零開始的,數(shù)組中第一個元素的索引是 0,第二個元素的索引是 1,依此類推:

>> a = [42, 8, 17] => [42, 8, 17] >> a[0] # Ruby 使用方括號獲取數(shù)組元素 => 42 >> a[1] => 8 >> a[2] => 17 >> a[-1] # 索引還可以是負數(shù) => 17

我們看到,在 Ruby 中是使用方括號來獲取數(shù)組元素的。除了這種方法,Ruby 還為一些常用的元素獲取操作提供了別名(synonym):6

>> a # 只是為了看一下 a 的值是什么 => [42, 8, 17] >> a.first => 42 >> a.second => 8 >> a.last => 17 >> a.last == a[-1] # 用 == 進行對比 => true

最后一行介紹了相等比較操作符?==,Ruby 和其他語言一樣還提供了對應的?!=(不等)等其他的操作符:

>> x = a.length # 和字符串一樣,數(shù)組也可以響應 length 方法 => 3 >> x == 3 => true >> x == 1 => false >> x != 1 => true >> x >= 1 => true >> x < 1 => false

除了?length(上述代碼的第一行)之外,數(shù)組還可以響應一堆其他的方法:

>> a => [42, 8, 17] >> a.sort => [8, 17, 42] >> a.reverse => [17, 8, 42] >> a.shuffle => [17, 42, 8] >> a => [42, 8, 17]

注意,上面的方法都沒有修改?a?的值。如果你想修改數(shù)組的值要使用對應的“炸彈(bang)”方法(之所以這么叫是因為這里的感嘆號經(jīng)常都讀作“bang”):

>> a => [42, 8, 17] >> a.sort! => [8, 17, 42] >> a => [8, 17, 42]

你還可以使用?push?方法向數(shù)組中添加元素,或者使用等價的?<<?操作符:

>> a.push(6) # 把 6 加到數(shù)組結(jié)尾 => [42, 8, 17, 6] >> a << 7 # 把 7 加到數(shù)組結(jié)尾 => [42, 8, 17, 6, 7] >> a << "foo" << "bar" # 串聯(lián)操作 => [42, 8, 17, 6, 7, "foo", "bar"]

最后一個例子說明你可以把添加操作串在一起操作;同時也說明,Ruby 不像很多其他的語言,數(shù)組可以包含不同類型的數(shù)據(jù)(本例中是數(shù)字和字符串混合)。

前面我們用?split?把字符串分割成字符串,我們還可以使用?join?方法進行相反的操作:

>> a => [42, 8, 17, 7, "foo", "bar"] >> a.join # 沒有連接符 => "428177foobar" >> a.join(', ') # 連接符是一個逗號和空格 => "42, 8, 17, 7, foo, bar"

和數(shù)組有點類似的是 Range,使用?to_a?方法把它轉(zhuǎn)換成數(shù)組或許更好理解:

>> 0..9 => 0..9 >> 0..9.to_a # 錯了,to_a 在 9 上調(diào)用了 NoMethodError: undefined method `to_a\' for 9:Fixnum >> (0..9).to_a # 調(diào)用 to_a 要用括號包住 Range => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

雖然?0..9?是一個合法的 Range,不過上面第二個表達式告訴我們調(diào)用方法時要加上括號。

Range 經(jīng)常被用來獲取一組數(shù)組元素:

>> a = %w[foo bar baz quux] # %w 創(chuàng)建一個元素為字符串的數(shù)組 => ["foo", "bar", "baz", "quux"] >> a[0..2] => ["foo", "bar", "baz"]

Range 也可使用字母:

>> ('a'..'e').to_a => ["a", "b", "c", "d", "e"]

4.3.2 塊

數(shù)組和 Range 可以響應的方法中有很多都可以跟著一個塊(block),這是 Ruby 中最強大也是最難理解的功能:

>> (1..5).each { |i| puts 2 * i } 2 4 6 8 10 => 1..5

這個代碼在 Range?(1..5)?上調(diào)用了?each?方法,然后又把?{ |i| puts 2*i }?這個塊傳遞給?each?方法。|i|?兩邊的豎杠在 Ruby 句法中是用來定義塊變量的。只有這個方法才知道如何處理后面跟著的塊。本例中,Range 的?each?方法會處理后面的塊,塊中有一個本地變量?i,each?會將 Range 中的各個值傳進塊中然后執(zhí)行相應的操作。

花括號是一種定義塊的方法,還有另一種方法可用:

>> (1..5).each do |i| ?> puts 2 * i >> end 2 4 6 8 10 => 1..5

塊可以多于一行,也經(jīng)常是多于一行的。本書中我們會遵照一個常用的約定,當塊只有一行簡單的代碼時使用花括號形式;當塊是一行很長的代碼,或者多行時使用?do..end?形式:

>> (1..5).each do |number| ?> puts 2 * number >> puts '--' >> end 2 -- 4 -- 6 -- 8 -- 10 -- => 1..5

上面的代碼用?number?代替了?i,我想告訴你的是任何變量名都可以使用。

除非你已經(jīng)有了一些編程知識,否則對塊的理解是沒有捷徑的。你要做的是多看,看得多了最后你就會習慣它的用法了。7幸好人類擅長于從實例中歸納出一般性。下面是一些例子,其中幾個用到了?map?方法:

>> 3.times { puts "Betelgeuse!" } # 3.times 后跟的塊沒有變量 "Betelgeuse!" "Betelgeuse!" "Betelgeuse!" => 3 >> (1..5).map { |i| i**2 } # ** 表示冪 => [1, 4, 9, 16, 25] >> %w[a b c] # 再說一下,%w 可以創(chuàng)建元素為字符串的數(shù)組 => ["a", "b", "c"] >> %w[a b c].map { |char| char.upcase } => ["A", "B", "C"] >> %w[A B C].map { |char| char.downcase } => ["a", "b", "c"]

上面的代碼說明,map?方法返回的是在數(shù)組或 Range 的每個元素上執(zhí)行塊中代碼后的結(jié)果。

現(xiàn)在我們就可以來理解一下我在?1.4.4 節(jié)中用來生成隨機二級域名的那行 Ruby 代碼了:

('a'..'z').to_a.shuffle[0..7].join

我們一步一步分解一下:

>> ('a'..'z').to_a # 字母表數(shù)組 => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"] >> ('a'..'z').to_a.shuffle # 打亂數(shù)組 => ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q", "b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"] >> ('a'..'z').to_a.shuffle[0..7] # 取出前面的 8 個元素 => ["f", "w", "i", "a", "h", "p", "c", "x"] >> ('a'..'z').to_a.shuffle[0..7].join # 將取出的元素合并成字符串 => "mznpybuj"

4.3.3 Hash 和 Symbol

Hash 本質(zhì)上就是數(shù)組的一個特例:你可以認為 Hash 基本上就是數(shù)組,只不過它的索引不局限于使用數(shù)字。(實際上在一些語言中,特別是 Perl,因為這個原因就把 Hash 叫做關聯(lián)數(shù)組(associative array)。)Hash 的索引(或者叫“鍵”)幾乎可以是任何對象。例如,我們可以使用字符串當鍵:

>> user = {} # {} 是一個空 Hash => {} >> user["first_name"] = "Michael" # 鍵為 "first_name",值為 "Michael" => "Michael" >> user["last_name"] = "Hartl" # 鍵為 "last_name",值為 "Hartl" => "Hartl" >> user["first_name"] # 獲取元素的方式類似數(shù)組 => "Michael" >> user # Hash 的字面量形式 => {"last_name"=>"Hartl", "first_name"=>"Michael"}

Hash 通過一對花括號中包含一些鍵值對的形式表示,只有一對花括號而沒有鍵值對({})就是一個空 Hash。需要注意,Hash 中的花括號和塊中的花括號不是一個概念。(是的,這可能會讓你迷惑。)不過,Hash 雖然和數(shù)組類似,但卻有一個很重要的區(qū)別:Hash 的元素沒有特定的順序。8?如果順序很重要的話就要使用數(shù)組了。

通過方括號的形式每次定義一個元素的方式不太敏捷,使用?=>?分隔的鍵值對這種字面量的形式定義 Hash 要簡潔得多,我們稱后一種方式為“hashrocket”:

>> user = { "first_name" => "Michael", "last_name" => "Hartl" } => {"last_name"=>"Hartl", "first_name"=>"Michael"}

在上面的代碼中我用到了一個 Ruby 句法約定,在左花括號后面和右花括號前面加入了一個空格,控制臺會忽略這些空格。(不要問我為什么這些空格是約定俗成的,或許是某個 Ruby 編程大牛喜歡這種形式,然后約定就產(chǎn)生了。)

目前為止我們的鍵用的都是字符串,但在 Rails 中用 Symbol 當鍵卻很常見。Symbol 看起來像字符串,只不過沒有包含在一對引號中,而是在前面加一個冒號。例如,:name?就是一個 Symbol。你可以把 Symbol 看成沒有約束的字符串:9

>> "name".split('') => ["n", "a", "m", "e"] >> :name.split('') NoMethodError: undefined method `split' for :name:Symbol >> "foobar".reverse => "raboof" >> :foobar.reverse NoMethodError: undefined method `reverse' for :foobar:Symbol

Symbol 是 Ruby 特有的一個數(shù)據(jù)類型,其他語言很少用到,初看起來感覺很奇怪,不過 Rails 經(jīng)常用到它,所以你很快就會習慣的。

用 Symbol 當鍵,我們可以按照如下的方式定義一個?user?Hash:

>> user = { :name => "Michael Hartl", :email => "michael@example.com" } => {:name=>"Michael Hartl", :email=>"michael@example.com"} >> user[:name] # 獲取 :name 對應的值 => "Michael Hartl" >> user[:password] # 獲取一個未定義的鍵對應的值 => nil

從上面的例子我們可以看出,Hash 中沒有定義的鍵對應的值是?nil。

因為 Symbol 當鍵的情況太普遍了,Ruby 1.9 干脆就為這種情況定義了一個新的句法:

>> h1 = { :name => "Michael Hartl", :email => "michael@example.com" } => {:name=>"Michael Hartl", :email=>"michael@example.com"} >> h2 = { name: "Michael Hartl", email: "michael@example.com" } => {:name=>"Michael Hartl", :email=>"michael@example.com"} >> h1 == h2 => true

第二個命令把 hashrocket 形式的鍵值對變成了鍵后跟著一個冒號然后再跟著一個值的形式:

{ name: "Michael Hartl", email: "michael@example.com" }

這種結(jié)構(gòu)更好的沿襲了其他語言(例如 JavaScript)中 Hash 的表現(xiàn)方式,在 Rails 社區(qū)中也越來越受歡迎。這兩種方式現(xiàn)在都在使用,所以你要能識別它們。本書后續(xù)內(nèi)容中大多數(shù)的 Hash 都會使用新的形式,在 Ruby 1.8.7 或之前的版本中是不可以使用的。如果你使用的是較早前的版本,你可以更新到 Ruby 1.9(推薦),或者使用舊的形式。

Hash 元素的值可以是任何對象,甚至是一個 Hash,如代碼 4.6 所示。

代碼 4.6?Hash 嵌套

>> params = {} # 定義一個名為 params(parameters 的簡稱)的 Hash => {} >> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" } => {:name=>"Michael Hartl", :email=>"mhartl@example.com"} >> params => {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}} >> params[:user][:email] => "mhartl@example.com"

這種 Hash 中有 Hash 的形式(或稱為 Hash 嵌套)在 Rails 中大量的使用,我們從?7.3 節(jié)開始會接觸到。

與數(shù)組和 Range 一樣,Hash 也可以響應?each?方法。例如,一個名為?flash?的 Hash,它的鍵是兩個條件判斷,:success?和?:error:

>> flash = { success: "It worked!", error: "It failed." } => {:success=>"It worked!", :error=>"It failed."} >> flash.each do |key, value| ?> puts "Key #{key.inspect} has value #{value.inspect}" >> end Key :success has value "It worked!" Key :error has value "It failed."

注意,數(shù)組的?each?方法后面的塊只有一個變量,而 Hash 的?each?后面的塊接受兩個變量,key?和?value。所以 Hash 的?each?方法每次遍歷都會以一個鍵值對為基本單位進行。

上面的示例中用到了很有用的?inspect?方法,返回被調(diào)用對象的字符串字面量表現(xiàn)形式:

>> puts (1..5).to_a # 把數(shù)組作為字符串輸出 1 2 3 4 5 >> puts (1..5).to_a.inspect # 輸出一個數(shù)組字面量形式 [1, 2, 3, 4, 5] >> puts :name, :name.inspect name :name >> puts "It worked!", "It worked!".inspect It worked! "It worked!"

順便說一下,因為使用?inspect?輸出對象的方式經(jīng)常使用,為此還有一個專門的快捷方式,p?方法:

>> p :name # 等價于 puts :name.inspect :name

4.3.4 重溫引入 CSS 的代碼

現(xiàn)在我們要重新認識一下代碼 4.1 中在布局中引入 CSS 的代碼:

<%= stylesheet_link_tag "application", :media => "all" %>

我們現(xiàn)在基本上可以理解這行代碼了。在?4.1 節(jié)中簡單的提到過,Rails 定義了一個特殊的函數(shù)用來引入樣式表,下面的代碼

stylesheet_link_tag "application", :media => "all"

就是對這個函數(shù)的調(diào)用。不過還有兩個奇怪的地方。第一,括號哪兒去了?因為在 Ruby 中,括號是可以省略的,下面的兩行代碼是等價的:

# 函數(shù)調(diào)用時括號是可以省略的 stylesheet_link_tag("application", :media => "all") stylesheet_link_tag "application", :media => "all"

第二,:media?部分顯然是一個 Hash,但是怎么沒用花括號?因為在調(diào)用函數(shù)時,如果 Hash 是最后一個參數(shù),它的花括號是可以省略的。下面的兩行代碼是等價的:

# Hash 是最后一個參數(shù)時花括號可以省略 stylesheet_link_tag "application", { :media => "all" } stylesheet_link_tag "application", :media => "all"

所以我們就看到了這樣一行代碼

stylesheet_link_tag "application", :media => "all"

它調(diào)用了?stylesheet_link_tag?函數(shù),傳進兩個參數(shù):一個是字符串,指明樣式表的路徑;另一個是 Hash,指明媒介類型。因為使用的是?<%= %>,函數(shù)的執(zhí)行結(jié)果會通過 ERb 插入模板中,如果你在瀏覽器中查看網(wǎng)頁的源代碼就會看到引入樣式表所用的 HTML(參見代碼 4.7)。(你可能會在 CSS 的文件名后看到額外的字符,例如??body=1。這是 Rails 加入的,可以確保 CSS 修改后瀏覽器會重新加載它。)

代碼 4.7?引入 CSS 的代碼生成的 HTML

<link href="/assets/application.css" media="all" rel="stylesheet" type="text/css" />

如果你打開?http://localhost:3000/assets/application.css?查看 CSS 的話,會發(fā)現(xiàn)是空的(除了一些注釋)。在第五章中我們會看介紹如何添加樣式。

4.4 Ruby 類

我們之前已經(jīng)說過 Ruby 中的一切都是對象,本節(jié)我們就會自己定義一些對象。Ruby 和其他面向?qū)ο?#xff08;object-oriented)編程語言一樣,使用類來組織方法。然后實例化(instantiate)類創(chuàng)建對象。如果你剛接觸面向?qū)ο缶幊?#xff0c;這些都似天書一般,那么讓我們來看一些實際的例子吧。

4.4.1 構(gòu)造器

我們看過很多例子使用類初始化對象,不過還沒有正式的初始化過。例如,我們使用一個雙引號初始化一個字符串,雙引號是字符串的字面構(gòu)造器(literal constructor):

>> s = "foobar" # 使用雙引號的字面構(gòu)造器 => "foobar" >> s.class => String

我們看到字符串可以響應?class?方法,返回的結(jié)果是字符串所屬的類。

除了使用字面構(gòu)造器之外,我們還可以使用等價的具名構(gòu)造器(named constructor),即在類名上調(diào)用?new?方法:10

>> s = String.new("foobar") # 字符串的具名構(gòu)造器 => "foobar" >> s.class => String >> s == "foobar" => true

上面的代碼和字面構(gòu)造器是等價的,只是更能表現(xiàn)我們的意圖。

數(shù)組和字符串類似:

>> a = Array.new([1, 3, 2]) => [1, 3, 2]

不過 Hash 就有些不同了。數(shù)組的構(gòu)造器?Array.new?可接受一個可選的參數(shù)指明數(shù)組的初始值,Hash.new?可接受一個參數(shù)指明元素的默認值,就是當鍵不存在時返回的值:

>> h = Hash.new => {} >> h[:foo] # 試圖獲取不存在的鍵 :foo 對應的值 => nil >> h = Hash.new(0) # 設置不存在的鍵返回 0 而不是 nil => {} >> h[:foo] => 0

在類上調(diào)用的方法,如本例的?new,我們稱之為類方法(class method)。在類上調(diào)用?new?得到的結(jié)果是這個類的一個對象,也叫做這個類的實例(instance)。在實例上調(diào)用的方法,例如?length,叫做實例方法(instance method)。

4.4.2 類的繼承

學習類時,理清類的繼承關系會很有用,我們可以使用?superclass?方法:

>> s = String.new("foobar") => "foobar" >> s.class # 查找 s 所屬的類 => String >> s.class.superclass # 查找 String 的父類 => Object >> s.class.superclass.superclass # Ruby 1.9 使用 BasicObject 作為基類 => BasicObject >> s.class.superclass.superclass.superclass => nil

這個繼承關系如圖 4.1 所示。我們可以看到,String?的父類是?Object,Object?的父類是?BasicObject,但是?BasicObject就沒有父類了。這樣的關系對每個 Ruby 對象都是適用的:只要在類的繼承關系上往上多走幾層就會發(fā)現(xiàn) Ruby 中的每個類最終都是繼承自?BasicObject,而其本身沒有父類。這就是“Ruby 中一切皆對象”技術(shù)層面的意義。

圖 4.1:String?類的繼承關系

要更深入的理解類,最好的方法就是自己動手編寫。我們來創(chuàng)建一個名為?Word?的類,包含一個名為?palindrome??方法,如果單詞順讀和反讀時都一樣則返回?true:

>> class Word >> def palindrome?(string) >> string == string.reverse >> end >> end => nil

我們可以按照下面的方式使用:

>> w = Word.new # 創(chuàng)建一個 Word 對象 => #<Word:0x22d0b20> >> w.palindrome?("foobar") => false >> w.palindrome?("level") => true

如果你覺得這個例子有點大題小做,很好,我們的目的達到了。定義一個新類,可是只創(chuàng)建一個可以接受一個字符串參數(shù)的方法,這么做很古怪。既然單詞是字符串,讓?Word?繼承?String?不就行了,如代碼 4.8 所示。(你要退出控制臺然后再在控制臺中輸入這寫代碼,這樣才能把之前的?Word?定義清除掉。)

代碼 4.8?在控制臺中定義?Word?類

>> class Word < String # Word 繼承自 String >> # 如果字符串和自己反轉(zhuǎn)后相等則返回 true >> def palindrome? >> self == self.reverse # self 代表這個字符串本身 >> end >> end => nil

上面代碼中的?Word < String?在 Ruby 中表示繼承(3.1.2 節(jié)中簡單介紹過),這樣除了剛定義的?palindrome??方法之外,Word?還擁有所有字符串擁有的方法:

>> s = Word.new("level") # 創(chuàng)建一個新的 Word,初始值為 level => "level" >> s.palindrome? # Word 實例可以響應 palindrome? 方法 => true >> s.length # Word 實例還繼承了字符串所有的常規(guī)方法 => 5

Word?繼承自?String,我們可以在控制臺中查看類的繼承關系:

>> s.class => Word >> s.class.superclass => String >> s.class.superclass.superclass => Object

繼承關系如圖 4.2 所示。

圖 4.2:代碼 4.8 中定義的?Word?類(非內(nèi)置類)的繼承關系

在代碼 4.8 中,注意,要檢查單詞和單詞的反轉(zhuǎn)是否相同,要在?Word?類中引用這個單詞,在 Ruby 中我們使用?self?進行引用:在?Word?類中,self?代表的就是對象本身。所以我們可以使用

self == self.reverse

來檢查單詞是否是一個回文。11

4.4.3 修改內(nèi)置的類

雖然繼承是個很強大的功能,不過在回文判斷的例子中,如果能把?palindrome??加入?String?類就更好了,這樣(除了其他對象外)我們就可以在字符串字面量上調(diào)用?palindrome??方法了。現(xiàn)在我們還不能直接調(diào)用:

>> "level".palindrome? NoMethodError: undefined method `palindrome?\' for "level":String

有點令人驚訝的是,Ruby 允許你這么做,Ruby 中的類可以被打開進行修改,允許像我們自己這樣的普通人添加一些方法:12

>> class String >> # 如果字符串和自己反轉(zhuǎn)后相等則返回 true >> def palindrome? >> self == self.reverse >> end >> end => nil >> "deified".palindrome? => true

(我不知道哪一個更牛:Ruby 允許向內(nèi)置的類中添加方法,或“deified(神化,奉為神明)”是個回文。)

可以修改內(nèi)置的類是個很強大的功能,不過功能強大意味著責任也大,如果沒有一個很好的理由,向內(nèi)置的類中添加方法被認為是不好的習慣。Rails 自然有很好的理由,例如,在 Web 應用程序中我們經(jīng)常要避免變量是空白(blank)的,像用戶名之類的就不應該是空格或空白,所以 Rails 為 Ruby 添加了一個?blank??方法。因為 Rails 控制臺會自動加載 Rails 添加的擴展功能,我們可以看一下示例(在?irb?就不可以):

>> "".blank? => true >> " ".empty? => false >> " ".blank? => true >> nil.blank? => true

我們可以看到,一個包含空格的字符串不是空的(empty),卻是空白的(blank)。還要注意,nil?也是空白的。因為?nil不是字符串,所以上面的代碼說明了 Rails 其實是把?blank??添加到?String?的基類?Object?上的。我們會在?8.2.1 節(jié)中介紹一些 Rails 擴展 Ruby 類的例子。)

4.4.4 控制器類

討論類和繼承時你可能覺得似曾相識,不錯,我們之前介紹過,在使用 StaticPages 控制器時(代碼 3.15):

class StaticPagesController < ApplicationControllerdef homeenddef helpenddef aboutend end

你現(xiàn)在可以理解,至少有點能理解,這些代碼的意思了:StaticPagesController?是一個類,繼承自?ApplicationController,StaticPagesController?類中有三個方法?home、help?和?about。因為 Rails 控制臺會加載本地的 Rails 環(huán)境,所以我們可以在控制臺中創(chuàng)建一個控制器來查看一下它的繼承關系:13

>> controller = StaticPagesController.new => #<StaticPagesController:0x22855d0> >> controller.class => StaticPagesController >> controller.class.superclass => ApplicationController >> controller.class.superclass.superclass => ActionController::Base >> controller.class.superclass.superclass.superclass => ActionController::Metal >> controller.class.superclass.superclass.superclass.superclass => AbstractController::Base >> controller.class.superclass.superclass.superclass.superclass.superclass => Object

這個繼承關系如圖 4.3 所示。

圖 4.3:StaticPages 控制器的繼承關系

我們還可以在控制臺中調(diào)用控制器的動作,動作其實就是方法:

>> controller.home => nil

home?動作的返回值為?nil,因為它是空的。

注意,動作沒有返回值,或至少沒返回真正需要的值。如我們在第三章看到的,home?動作的目的是渲染網(wǎng)頁,而不是返回一個值。不過,我記得沒有在任何地方調(diào)用過?StaticPagesController.new,這是怎么回事?

原因在于,Rails 是用 Ruby 編寫的,但 Rails 不是 Ruby。有些 Rails 類就像普通的 Ruby 類一樣,不過也有些則得益于 Rails 的強大功能。Rails 是單獨的一門學問,應該區(qū)別于 Ruby 進行學習和理解。這就是為什么,如果你的興趣是開發(fā) Web 應用程序,我建議你先學 Rails 再學 Ruby,然后再回到 Rails 上的原因。

4.4.5 用戶類

我們通過創(chuàng)建一個完整的類來結(jié)束對 Ruby 的介紹,一個?User?類,提前實現(xiàn)第六章的 User 模型。

到目前為止,我們都是在控制臺中定義類的,這樣很快捷,但也有點不爽。現(xiàn)在我們要在應用程序的根目錄創(chuàng)建一個名為?example_user.rb?的文件,寫入代碼 4.9 中的內(nèi)容。

代碼 4.9?User?類的代碼?
example_user.rb

class Userattr_accessor :name, :emaildef initialize(attributes = {})@name = attributes[:name]@email = attributes[:email]enddef formatted_email"#{@name} <#{@email}>"end end

上面的代碼有很多要說明的,我們一步步來。先看下面這行:

attr_accessor :name, :email

它為用戶的名字和 Email 地址創(chuàng)建了屬性訪問器(attribute accessors)。也就是定義了“獲取(getter)”和“設定(setter)”方法,用來取回和賦值?@name?和?@email?實例變量,我們在?2.2.2 節(jié)中介紹過實例變量。在 Rails 中,實例變量的意義在于,它們自動的在視圖中可用。而通常實例變量的作用是用來在 Ruby 類中不同的方法之間傳遞變量值。(稍后會更詳細的介紹這點。)實例變量總是以?@?符號開頭,如果未定義則其值為?nil。

第一個方法,initialize,在 Ruby 中有特殊意義:當我們執(zhí)行?User.new?時會調(diào)用該方法。這個?initialize?方法可以接受一個參數(shù),attributes:

def initialize(attributes = {})@name = attributes[:name]@email = attributes[:email]end

attributes?變量的初始值是一個空的 Hash,所以我們可以定義一個沒有名字或沒有 Email 地址的用戶(回想一下?4.3.3 節(jié),如果鍵不存在則返回?nil,所以如果沒定義?:name?鍵,則?attributes[:name]?會返回?nil,attributes[:email]?也是一樣)。

最后,定義了一個名為?formatted_email?的方法,它使用被賦了值的?@name?和?@email?變量進行插值,組成一個格式良好的用戶 Email 地址(4.2.2 節(jié)):

def formatted_email"#{@name} <#{@email}>"end

因為?@name?和?@email?都是實例變量(如?@?符號指明),所以它們在?formatted_email?方法中自動可見。

讓我們打開控制臺,加載(require)這個文件,實際操作一下這個用戶類:

>> require './example_user' # 這就是加載文件的方式 => ["User"] >> example = User.new => #<User:0x224ceec @email=nil, @name=nil> >> example.name # 返回 nil,因為 attributes[:name] 是 nil => nil >> example.name = "Example User" # 賦值一個非 nil 的名字 => "Example User" >> example.email = "user@example.com" # 賦值一個非 nil 的 Email 地址 => "user@example.com" >> example.formatted_email => "Example User <user@example.com>"

上面代碼中的點號?.?在 Unix 中是指“當前目錄”,./example_user?告訴 Ruby 在當前目錄中尋找這個文件。接下來的代碼創(chuàng)建了一個空的用戶,然后通過直接賦值給相應的屬性來提供他的名字和 Email 地址(因為有了代碼 4.9 中?attr_accessor?那行才能進行賦值操作)。我們輸入

example.name = "Example User"

Ruby 會將?@name?變量的值設為?"Example User"(email?屬性類似),然后可以在?formatted_email?中使用。

如?4.3.4 節(jié)中介紹的,如果最后一個參數(shù)是 Hash,我們就可以省略花括號,我們可以把一個預先定義好的 Hash 傳遞給?initialize?方法來創(chuàng)建另一用戶:

>> user = User.new(name: "Michael Hartl", email: "mhartl@example.com") => #<User:0x225167c @email="mhartl@example.com", @name="Michael Hartl"> >> user.formatted_email => "Michael Hartl <mhartl@example.com>"

從第七章開始,我們會使用 Hash 初始化對象,這種技術(shù)叫做“mass assignment”,在 Rails 中很常用。

4.5 小節(jié)

現(xiàn)在結(jié)束對 Ruby 語言的介紹。在第五章我們會好好的利用這些知識來開發(fā)示例程序。

我們不會使用?4.4.5 節(jié)中創(chuàng)建的?example_user.rb?文件,所以我建議把它刪除:

$ rm example_user.rb

然后把其他的改動提交到代碼倉庫中:

$ git add . $ git commit -m "Add a full_title helper"

4.6 練習

  • 將下面代碼 4.10 中的問號換成合適的方法,結(jié)合split、shuffle?和?join?實現(xiàn)一個函數(shù),把一個給定字符串中的字符順序打亂。
  • 以下面代碼 4.11 為藍本,將?shuffle?方法添加到?String?類中。
  • 創(chuàng)建三個 Hash,分別名為?person1、person2?和?person3,將名和姓對應到?:first?和?:last?鍵上。再創(chuàng)建一個名為?params?的 Hash,使?params[:father]?對應?person1,params[:mother]?對應?person2,params[:child]?對應?person3。驗證一下?params[:father][:name]?的值是否正確。
  • 找一個在線的 Ruby API 文檔,閱讀?Hash?的?merge?方法的使用方法。
  • 跟著?Ruby Koans14?學習 Ruby 入門知識。
  • 代碼 4.10?打亂字符串函數(shù)的骨架

    >> def string_shuffle(s) >> s.split('').?.? >> end => nil >> string_shuffle("foobar")

    代碼 4.11?添加到?String?類的?shuffle?方法骨架

    >> class String >> def shuffle >> self.split('').?.? >> end >> end => nil >> "foobar".shuffle ? 第三章 基本靜態(tài)的頁面第五章 完善布局 ?
  • 如果幫助函數(shù)是針對某個特定控制器的,你應該把它放進該控制器相應的幫助文件中。例如,為 StaticPages 控制器創(chuàng)建的幫助函數(shù)一般放在?app/helper/static_pages_helper.rb?中。在這個例子中,我們會把?full_title?這個幫助函數(shù)用在網(wǎng)站內(nèi)所有的網(wǎng)頁中,針對這種情況 Rails 提供了一個特別的文件:app/helper/application_helper.rb。
  • 關于“foo”和“bar”,以及不太相關的“foobar”和“FUBAR”的起源,請查看?Jargon File 中介紹“foo”的文章。
  • 熟悉 Perl 或 PHP 的編程人員可以把這個功能與自動插值美元符號開頭的變量相對應,例如?"foo $bar"。
  • 很抱歉本章在函數(shù)和方法之間隨意的來回使用。在 Ruby 中這二者是同一個概念:所有的方法都是函數(shù),所有的函數(shù)也都是方法,因為一切皆對象。
  • 其實這里還有一個地方我們還不能理解,那就是 Rails 是怎么把這些聯(lián)系在一起的:把 URI 映射到動作上,full_title?幫助函數(shù)可以在視圖中使用,等。這是個很有意思的話題,我建議你以后好好的了解一下,不過使用 Rails 并不需要完全了解 Rails 的運作機理。(若想更深入的了解 Rails,我推薦閱讀 Obie Fernandez 的《Rails 3 之道》。)
  • 下面代碼中使用的?second?方法不是 Ruby 定義的,而是 Rails 添加的。在這里可以使用這個方法是因為 Rails 控制臺會自動加載 Rails 對 Ruby 的功能擴展。
  • 塊是閉包(closure),知道這一點對資深編程人員可能會有點幫助。閉包是一種匿名函數(shù),其中附帶了一些數(shù)據(jù)。
  • 在 Ruby 1.9 中,其實會按照元素輸入時的順序保存 Hash,不過依賴順序顯然是不明智的。
  • 沒有了約束的好處是,Symbol 很容易進行比較,字符串要按照字母一個一個的比較,而 Symbol 只需進行一次操作。這就使得 Symbol 成為 Hash 鍵的最佳選擇。
  • 返回的結(jié)果可能由于 Ruby 版本的不同而有所不同。這個例子假設你使用的是 Ruby 1.9.3。
  • 關于 Ruby 類和?self?關鍵字,請閱讀?RailsTips?上的《Class and Instance Variables in Ruby》一文。
  • 了解 JavaScript 的人可能知道這個功能與使用內(nèi)置的類原型對象擴充類的方式類似。(感謝讀者?Erik Eldridge?指出這一點。)
  • 你沒必要知道繼承關系中的每個類。我也不知道它們都是干什么的,而我從 2005 年就開始使用 Ruby on Rails 進行開發(fā)了。這可能意味著了以下兩個問題中的一個,第一,我是個廢柴,第二,你不需要知道所有的內(nèi)在知識也能成為熟練的 Rails 開發(fā)者。我們當然都希望是第二點。
  • http://rubykoans.com/


  • http://yongyuan.name/pcvwithpython//chapter4.html

    總結(jié)

    以上是生活随笔為你收集整理的第四章 Rails 背后的 Ruby的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    国产精品久久 | 免费黄色在线网址 | 日韩久久网站 | 午夜av剧场| www.夜夜骑.com | 久久久免费高清视频 | 亚洲欧美视屏 | 国产中文 | 国产69精品久久久久久 | 久久超碰97| 久久久久久久国产精品影院 | 亚洲香蕉在线观看 | 综合天天久久 | 日日久视频| 91高清免费在线观看 | 国产尤物视频在线 | 性色在线视频 | 99这里只有久久精品视频 | 久久福利精品 | 2021久久| 91看片成人 | 国产高清视频免费观看 | 久草免费新视频 | 日韩黄色大片在线观看 | 国产精品丝袜在线 | 欧美性久久久 | 国产精品99精品 | 夜夜狠狠 | 国产色女 | 国产中文字幕av | 中文字幕在线免费97 | 精品国产一区二区三区蜜臀 | 日韩精品欧美精品 | 久久久精品在线观看 | 亚洲国产成人在线 | 午夜视频在线观看一区二区三区 | 91视频最新网址 | 久久久久亚洲精品成人网小说 | 一级免费片 | 五月婷婷视频在线观看 | 日韩av影视 | 久久精品日产第一区二区三区乱码 | 欧美激情视频一二区 | 欧美成年黄网站色视频 | 性色av一区二区三区在线观看 | 99热九九这里只有精品10 | 日韩精品中文字幕在线 | 国产成人精品久久亚洲高清不卡 | 成人国产精品免费观看 | 久久久久亚洲精品男人的天堂 | 久久久久久久久久久久亚洲 | 午夜精品久久久久 | 伊人热 | 人人爽久久久噜噜噜电影 | 成人国产精品av | 亚洲精品乱码久久久久久 | 天天操天天射天天爱 | 久久久久影视 | 日韩在线免费视频 | 日韩av有码在线 | 日韩成人邪恶影片 | 欧洲一区二区在线观看 | 久久婷亚洲五月一区天天躁 | 日韩欧美成 | 中文字幕在线观看91 | 欧洲精品亚洲精品 | 婷婷网站天天婷婷网站 | 中国一级特黄毛片大片久久 | 99久久日韩精品免费热麻豆美女 | wwwwwww黄| 色欧美视频 | 四虎成人免费观看 | 999国产精品视频 | 免费高清在线一区 | 在线91av| 伊人天天狠天天添日日拍 | 亚洲无在线 | 激情网婷婷 | 在线观看av片| 在线观看免费 | 色婷婷狠狠干 | 91麻豆精品国产91久久久久 | 午夜在线看片 | 国产资源在线视频 | 在线免费性生活片 | 亚洲资源网 | 免费激情在线电影 | 色狠狠综合天天综合综合 | 婷婷亚洲最大 | 亚洲激情精品 | 免费在线国产视频 | 亚洲人人爱 | 伊人av综合 | 91日韩精品一区 | 久久久久女人精品毛片九一 | 手机av资源 | 久久久久久久久黄色 | 西西444www高清大胆 | 丝袜精品视频 | 九九热精品国产 | 国产永久免费观看 | av成人在线播放 | 最新日韩视频在线观看 | 久久人网 | 免费成人在线观看视频 | 久久久麻豆精品一区二区 | 国产美女精品在线 | 亚洲每日更新 | 国产精品com | 五月天综合 | 偷拍精偷拍精品欧洲亚洲网站 | 精品1区2区3区 | av高清网站在线观看 | 蜜臀久久99精品久久久酒店新书 | 丰满少妇在线观看网站 | 天天干天天拍天天操 | 91在线视频精品 | 精品福利国产 | 激情久久小说 | 久久视频在线观看 | 国产精品999久久久 久产久精国产品 | 国产亚洲精品美女久久 | 91人人视频在线观看 | 色视频国产直接看 | 精品999国产| 一区二区三区在线免费播放 | 三级在线视频播放 | 亚洲电影在线看 | 国产精品久久一区二区无卡 | 国产精品一区二区在线观看免费 | 97影视| 日日操夜夜操狠狠操 | 久久久久久久久久久网 | 伊人午夜视频 | 亚洲永久精品一区 | 色资源中文字幕 | 久操视频在线 | 日韩欧美在线综合网 | 2023亚洲精品国偷拍自产在线 | 69视频在线 | 天天视频色 | 曰韩精品| 国内精品毛片 | 久久亚洲婷婷 | 日日干夜夜干 | 成年人免费看片 | bbb搡bbb爽爽爽 | 色婷婷激情四射 | 91视频免费网址 | 国产一区二区三区高清播放 | 久久成人久久 | 91麻豆精品国产91久久久无限制版 | 不卡av电影在线观看 | 久久久久久综合网天天 | 国产在线播放不卡 | 噜噜色官网| 97精品电影院 | 久久久国产精品网站 | 九九三级毛片 | 97精品国产97久久久久久免费 | 国产视频网站在线观看 | 亚洲国产欧美一区二区三区丁香婷 | 91福利免费 | 973理论片235影院9 | 精品 激情 | 丝袜美腿亚洲 | 三级小视频在线观看 | 999久久a精品合区久久久 | av夜夜操 | 国产黄色在线网站 | 最新日韩电影 | 欧美极度另类 | 麻豆av电影| 国产永久免费高清在线观看视频 | 91天堂在线观看 | 天天曰天天曰 | .国产精品成人自产拍在线观看6 | 亚洲精品乱码久久久久久久久久 | 久草网站在线 | 国产午夜三级 | 国产视频每日更新 | 日本三级全黄少妇三2023 | 久久无码精品一区二区三区 | 日韩免费播放 | 午夜在线观看一区 | 少妇bbw搡bbbb搡bbbb| 欧美日韩中文国产一区发布 | 亚洲日韩中文字幕 | 欧美精品乱码久久久久久按摩 | 国产精品嫩草55av | 久99久在线 | 国产成人精品久久亚洲高清不卡 | 久久伊人国产精品 | 国产黄色一级片在线 | 黄色亚洲片 | 97人人人人 | 日日夜夜中文字幕 | 天天躁日日躁狠狠 | 国产黄色一级片 | 色噜噜狠狠色综合中国 | 成全在线视频免费观看 | 国产亚洲情侣一区二区无 | 国产黄色免费观看 | 久久精品国产成人精品 | 久久99国产精品二区护士 | 亚洲精品视频免费在线观看 | 免费久久99精品国产 | 色wwwww| 久久精品视频播放 | 日本最新一区二区三区 | 天天爱天天爽 | 天天摸天天舔天天操 | 99 色 | 97av在线视频 | 久久久91精品国产一区二区精品 | 中文字幕在线观看完整版电影 | 免费网站在线观看成人 | 亚洲va欧美va国产va黑人 | 成人91av | 日韩久久精品一区二区三区 | 69av国产 | 91色综合 | 亚洲综合激情网 | 亚洲精品美女 | 欧美五月婷婷 | 国产美女精品久久久 | 91你懂的 | 日韩av一区二区三区在线观看 | 激情视频久久 | 久久久综合电影 | 久久999久久| 成人资源站 | 亚洲最新视频在线 | 久热av| 免费观看av | 懂色av一区二区三区蜜臀 | 成人免费视频网 | 奇米影视在线99精品 | 久久亚洲私人国产精品 | 伊人亚洲综合网 | 在线天堂8√ | 日韩av片免费在线观看 | 日本精品一 | 午夜av在线播放 | 碰超在线观看 | 久久的色 | 去看片| 欧美精品v国产精品 | 日韩免费视频 | 天天婷婷 | 曰本三级在线 | 在线av资源 | 久久亚洲国产精品 | 香蕉视频日本 | 久久国产视频网 | 天天草天天干天天 | 在线婷婷 | 波多野结衣视频一区二区 | 日韩欧美精品一区二区三区经典 | 国产 色| 国产精品视频永久免费播放 | 手机看片午夜 | jizz欧美性9 国产一区高清在线观看 | 99免费在线视频 | 99久久99久久精品 | 久久久久久久久久久久亚洲 | 911亚洲精品第一 | 国产无吗一区二区三区在线欢 | 欧美黄色特级片 | 国产在线观看污片 | 欧美日韩国产精品一区二区 | 久久无码精品一区二区三区 | 激情av网 | 91色影院 | 最新在线你懂的 | 色噜噜日韩精品欧美一区二区 | 亚洲1区在线| 日韩三区在线观看 | 麻豆久久久久 | 久久精品精品电影网 | 草久在线播放 | 人人爽人人爽人人片av免 | 中文视频在线看 | 精品人妖videos欧美人妖 | 天天操天天射天天爱 | 日韩综合一区二区三区 | 天天天天色综合 | 国产亚洲精品久久久网站好莱 | 久久人人爽人人爽人人片av软件 | 国产黄网在线 | 国产夫妻性生活自拍 | 狠狠躁天天躁 | 日韩欧美精选 | 日韩免费在线视频观看 | 97在线免费观看视频 | 中文字幕 国产 一区 | 欧美久久久久 | 丁香资源影视免费观看 | 国产精品久久久999 国产91九色视频 | 久久久久久久久久久精 | 亚洲精品456在线播放乱码 | 一级免费片 | 久久久久久久国产精品影院 | 久久精品视频观看 | 国产白浆在线观看 | 亚洲成人av免费 | 91香蕉国产 | 久久亚洲综合国产精品99麻豆的功能介绍 | 欧美电影黄色 | 欧美午夜久久久 | 久久不卡免费视频 | 人人爽人人做 | 成人app在线免费观看 | av中文字幕网 | 超碰97中文 | 天天色天天骑天天射 | 欧美日韩三区二区 | 五月婷婷中文字幕 | 免费在线观看污网站 | 国产精品久久久久久久久久久久久久 | 亚洲国产97在线精品一区 | 国产精品一区二区果冻传媒 | 亚洲人天堂| 亚洲va综合va国产va中文 | 日韩精品中文字幕在线 | 国内精品久久久久 | 中文字幕在线观看完整 | av电影亚洲 | 中文字幕国语官网在线视频 | 日韩av影视在线 | 中文字幕色播 | 黄色成人91 | 99热超碰| 黄色小网站免费看 | 日本在线精品视频 | 国产精品男女视频 | 亚洲 欧美 日韩 综合 | 91福利在线观看 | 亚洲国产精品久久 | 免费看av在线 | 国产免费观看久久黄 | 色a网 | 日韩精品一区二区三区免费视频观看 | 一级片免费视频 | 久久久综合九色合综国产精品 | 久久精品国产免费看久久精品 | 最近高清中文字幕在线国语5 | 韩国av免费 | 玖玖在线精品 | 欧美人体xx | 成人啪啪18免费游戏链接 | 波多野结衣在线中文字幕 | 香蕉一区 | 手机在线观看国产精品 | 波多野结衣电影一区二区三区 | 日女人电影 | 中文字幕av在线播放 | 亚洲国产精品电影 | 亚洲经典视频在线观看 | 中文字幕高清在线播放 | 亚洲人成在线电影 | 深爱婷婷久久综合 | 亚洲伊人av | 欧美精品久久久久久久久免 | 亚洲国产资源 | 热久久电影 | 一区二区三区 亚洲 | 天天操天天射天天插 | 播五月综合 | 成人在线视频网 | 九月婷婷色 | 国产一级视频在线观看 | 91最新视频 | 欧美在线视频精品 | 一级a毛片高清视频 | 日韩1页 | 亚洲欧美日韩一区二区三区在线观看 | 国内久久精品 | 在线观看蜜桃视频 | 视频国产一区二区三区 | 天天干天天操天天射 | 国产剧情久久 | 久久久久精 | 午夜精品久久久久久久久久久久 | 草久在线视频 | 欧美成人手机版 | 日韩三级在线 | 久久美女电影 | 久久精品爱爱视频 | 最近在线中文字幕 | 国产日韩欧美在线影视 | 中文字幕亚洲欧美日韩2019 | 免费a网| 色老板在线 | 国内精品久久久久久久影视简单 | 亚洲国产中文字幕在线视频综合 | 日韩一二三区不卡 | 五月天伊人网 | 久久久国产精品人人片99精片欧美一 | 在线观看欧美成人 | 911在线| 国产欧美高清 | 免费在线观看av网站 | 成人一级片视频 | 中文字幕人成乱码在线观看 | 成人黄大片 | 日韩高清 一区 | 97色综合 | 日韩av高清在线观看 | 免费在线观看av片 | 亚洲精品视频大全 | 精品国产一区二区三区久久久蜜臀 | h动漫中文字幕 | 九九九视频精品 | 亚洲国产日韩一区 | 91精品区 | 黄色av一级片 | 五月天综合色激情 | 日韩高清毛片 | 中文字幕日韩免费视频 | 国产成人久久久久 | 免费黄色在线网站 | 天天干天天操av | 在线天堂中文在线资源网 | 精品伦理一区二区三区 | 国产成人久久精品一区二区三区 | 国内小视频在线观看 | 天天干天天干天天干 | 色婷婷欧美| 欧美韩国在线 | 丁香六月激情 | 99久久99久久综合 | 五月婷婷久久综合 | 91在线视频免费 | 亚洲在线视频免费观看 | 一级免费片 | 五月天堂网 | 色综合欧洲 | 色婷婷五| 91传媒激情理伦片 | 亚洲第一av在线 | 成人三级网站在线观看 | 日韩免费视频 | 天天拍天天干 | 婷婷亚洲五月色综合 | 五月天丁香 | 99精品热| 亚洲国产精品推荐 | 国产中年夫妇高潮精品视频 | 久久久99精品免费观看乱色 | 国产精选在线观看 | 日日夜夜添| 欧美日韩破处 | 97在线影视| 亚洲精品在线免费播放 | 激情开心网站 | 女人18毛片a级毛片一区二区 | 欧美日韩国产亚洲乱码字幕 | 天天爱天天 | 免费日韩视 | 五月av在线| 精品专区一区二区 | 1024久久 | 国产视频精品免费 | 蜜臀av在线一区二区三区 | 亚洲免费在线看 | 九九热只有这里有精品 | 热久久这里只有精品 | 一级一片免费看 | 久久精品国产亚洲精品 | 97色涩| 色婷婷综合激情 | 日日爱av | 天天色天天色 | 日本性xxx| 国产97免费 | av播放在线| 亚洲五月六月 | 美女久久久久 | 日韩欧美高清在线 | 韩国一区二区三区视频 | 亚洲激情综合 | 亚洲成av人片在线观看香蕉 | 中文字幕视频网 | 欧美精品久久久久久 | 五月婷婷综合久久 | 97超碰总站| 日韩高清一区二区 | 国产精品久久久久久模特 | 激情婷婷色 | 在线观看片| 国产精品黄色 | 成人一区二区三区中文字幕 | 夜色资源站国产www在线视频 | 欧美日韩一区二区三区在线观看视频 | 中文字幕一区二区三区在线播放 | 五月婷婷激情综合 | 精品国产一区二区在线 | 午夜成人影视 | 久久免费视频网 | 亚洲国产资源 | 91精品系列| 不卡视频在线看 | 伊人狠狠色丁香婷婷综合 | 精品国产一区二区三区av性色 | 97超碰中文字幕 | 欧美在线久久 | 亚洲电影一区二区 | 日韩一级理论片 | 六月丁香婷婷在线 | av在线播放一区二区三区 | 欧美一区视频 | 久久国产一区二区三区 | 人人爽人人澡 | 天天做日日做天天爽视频免费 | 亚洲爱av | av免费在线观 | 亚洲欧美一区二区三区孕妇写真 | 婷婷丁香五 | 国产免费又粗又猛又爽 | 狠狠狠色丁香婷婷综合激情 | 在线观看视频一区二区 | 91在线观看视频网站 | 久久精品播放 | 五月婷婷毛片 | 亚洲国产丝袜在线观看 | 337p日本大胆噜噜噜噜 | 99视频在线免费 | 91九色自拍 | 久久这里只有精品23 | 少妇bbb搡bbbb搡bbbb′ | 绯色av一区 | 成人在线观看你懂的 | 精品久久影院 | 看全黄大色黄大片 | 国产一区视频免费在线观看 | 久久精品亚洲综合专区 | 婷婷色 亚洲 | 色av资源网 | 欧美大码xxxx| 一区二区精品久久 | 国产精品国产三级国产不产一地 | 欧美日韩一区二区免费在线观看 | 18国产精品白浆在线观看免费 | 久久激情视频免费观看 | 久久久国产精华液 | 久久艹免费 | 四虎成人精品永久免费av九九 | 精品久久久久久一区二区里番 | av网站免费看| 欧美日韩调教 | 亚洲精品婷婷 | 狠狠狠狠干 | 久久9视频 | 国产粉嫩在线观看 | 国产又粗又猛又黄 | 日韩在线视频网站 | 久久只精品99品免费久23小说 | 国产精品一区免费在线观看 | 黄网站色成年免费观看 | 国产精品123 | 久久艹国产 | 麻豆综合网 | 免费在线观看av | 91麻豆精品国产91久久久使用方法 | 美女视频是黄的免费观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产馆在线播放 | av在线播放观看 | 懂色av一区二区在线播放 | av成年人电影 | 国产精品久久久久久高潮 | 91网在线看| 亚洲,播放 | 国产精品永久在线观看 | 亚洲国产精品va在线看黑人 | 国产成人一区二区三区免费看 | 91精品国产电影 | 国产一区二区在线观看视频 | 丁香激情五月婷婷 | www.久久久| 日韩精品专区在线影院重磅 | 亚洲精品久久久久久久不卡四虎 | 国产精久久久久久妇女av | 五月天综合婷婷 | 亚洲韩国一区二区三区 | 亚洲天堂网视频在线观看 | 精品婷婷| 六月丁香激情综合 | 久久久噜噜噜久久久 | 91精品国产99久久久久久久 | 最近高清中文字幕在线国语5 | 日韩视频中文字幕在线观看 | 综合网欧美 | 91麻豆操 | 三级a视频 | 亚洲国产午夜视频 | 99视频在线看 | 日本最新中文字幕 | www免费| 91| 国产精品一区二区久久精品爱涩 | 成人av影视在线 | 女女av在线 | 欧美日韩高清在线一区 | 99精彩视频在线观看免费 | 91视频网址入口 | 国产成人一区三区 | 精品一区二三区 | 视频国产区 | 高清不卡一区二区在线 | 日韩一区二区免费播放 | 毛片美女网站 | 在线观看欧美成人 | 免费在线国产精品 | 91亚洲欧美 | 黄色大片入口 | 天天综合成人 | 99这里只有精品99 | 亚洲狠狠丁香婷婷综合久久久 | 欧美成人一二区 | 成人亚洲精品国产www | 成人av资源网 | av成人亚洲 | 在线观看黄色小视频 | 精品视频在线免费 | 狠狠色狠狠色综合系列 | 国产精品久久久视频 | 日本视频精品 | 亚洲精品av在线 | 欧美国产不卡 | 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 人人干网站 | 成人毛片在线观看视频 | 日韩黄在线观看 | 五月婷香蕉久色在线看 | 中文字幕亚洲不卡 | 欧美疯狂性受xxxxx另类 | 欧美性生活免费看 | 五月婷婷激情五月 | 日韩av电影免费观看 | 去干成人网| 久久综合色婷婷 | 亚洲国产日本 | 国产精品欧美 | 中文字幕在线观看免费高清电影 | 永久中文字幕 | 91精品视频免费看 | 欧美日韩一区二区在线观看 | 中文字幕综合在线 | 狠狠色香婷婷久久亚洲精品 | 日韩.com| 青青河边草免费观看完整版高清 | 一区二区三区 亚洲 | 91在线免费播放视频 | 在线国产专区 | 在线观看v片 | 国产理伦在线 | 国产美女被啪进深处喷白浆视频 | 一级黄网| 日韩a在线看 | 欧美精品一区在线 | 亚洲国产欧美一区二区三区丁香婷 | 成 人 黄 色视频免费播放 | 2021av在线| 波多野结衣电影一区二区三区 | 欧美日韩成人一区 | 久久免费视频观看 | 蜜臀av性久久久久蜜臀aⅴ涩爱 | 欧美一区二区三区在线视频观看 | 亚洲理论片在线观看 | 豆豆色资源网xfplay | 中文字幕在线一二 | 久久婷婷激情 | 久久精品www人人爽人人 | 国产一区二区三区免费视频 | 色婷婷激婷婷情综天天 | 97手机电影网 | 日韩高清在线一区 | 在线亚洲人成电影网站色www | 国产成人三级在线观看 | 国内精品中文字幕 | 国产在线p | 天天综合成人网 | 天天在线视频色 | 中文字幕免费成人 | 午夜精品一二三区 | 亚洲精品永久免费视频 | 亚洲四虎在线 | 久久激情片 | 亚洲伊人婷婷 | 成人在线观看网址 | 久久久久久综合 | 夜夜操网| 久久精品综合一区 | 丁香花在线视频观看免费 | 日本一区二区不卡高清 | 激情综合中文娱乐网 | 成人国产在线 | 国产一区二区在线视频观看 | 超碰97公开 | 中文字幕一区二区三区在线播放 | 亚洲乱码精品 | 久久9999久久免费精品国产 | 国产在线播放一区 | av在线a | 国内外成人免费在线视频 | 粉嫩av一区二区三区四区五区 | 美女视频国产 | 久久精品欧美一区 | 一区二区影视 | 日韩网 | 日韩中文字幕免费 | 国产成人99久久亚洲综合精品 | 亚洲免费公开视频 | 高清av免费一区中文字幕 | 久久视频这里只有精品 | 日韩精品一区二区电影 | 日韩在线网址 | www久久久久 | 福利久久久| 色在线亚洲| 国产一区视频导航 | 成人黄色毛片视频 | 欧美日韩1区2区 | 国产精品成人自产拍在线观看 | 九九九电影免费看 | 狠狠色丁香久久婷婷综合_中 | 香蕉久久久久久av成人 | 天天操夜操视频 | 精品高清美女精品国产区 | 欧美日在线观看 | 永久免费的啪啪网站免费观看浪潮 | 久艹视频在线免费观看 | 最近中文字幕高清字幕在线视频 | av三区在线| 国产美女视频 | 少妇按摩av| 人人超碰免费 | 色婷婷88av视频一二三区 | 91精品入口| 亚洲最大av网站 | 国产精品视频全国免费观看 | 久久五月婷婷丁香社区 | 久久精品视频国产 | 免费久久99精品国产婷婷六月 | 91麻豆看国产在线紧急地址 | 免费网站在线 | 中文字幕丝袜 | 久草在线资源免费 | 在线中文字幕观看 | 久久久三级视频 | 欧美91精品国产自产 | 丝袜美腿亚洲综合 | 国产精品视频久久 | 国产精品 国产精品 | 亚洲精品乱码久久久久久蜜桃动漫 | 色综合久久久久久久 | 黄视频色网站 | 96视频免费在线观看 | 久久午夜免费视频 | 亚洲一区网 | 香蕉视频在线免费 | 91自拍成人 | 国产免费作爱视频 | 亚洲免费视频观看 | 久久久久久毛片 | 久久久久久久久久电影 | 91麻豆精品 | 人人爽人人干 | 成 人 黄 色 视频免费播放 | 精品国产99 | 久久综合久久鬼 | 天天夜夜狠狠操 | 在线观看亚洲a | 免费 在线 中文 日本 | 91丨九色丨国产女 | 日韩av片在线| 国产 日韩 欧美 中文 在线播放 | 操老逼免费视频 | 蜜臀av在线一区二区三区 | 亚洲美女免费精品视频在线观看 | 成人免费xxxxxx视频 | 成人日批视频 | a视频在线播放 | 日韩av一区二区在线影视 | 亚洲欧洲精品一区二区精品久久久 | 97超碰资源站 | 日本黄色免费大片 | 欧洲精品视频一区二区 | 激情综合国产 | 国产精品激情偷乱一区二区∴ | 国产成人精品福利 | 欧美激情h | 激情综合一区 | 久热久草| 成人香蕉视频 | 天天综合网 天天综合色 | 五月天伊人 | av网址aaa| 精品国模一区二区 | 国产成人精品久久久久蜜臀 | 精品国产一区二区三区噜噜噜 | 国产福利91精品 | 亚洲春色综合另类校园电影 | 久章草在线观看 | 天天干,天天草 | 久久综合电影 | 国产视频91在线 | 国产一区二区在线免费 | 日女人免费视频 | 中文字幕刺激在线 | www.国产在线观看 | 五月婷婷综合激情 | 手机在线看永久av片免费 | 91久久久久久久 | 国产精品观看在线亚洲人成网 | 国产精品久久久久久久午夜 | 欧亚日韩精品一区二区在线 | 91成人观看 | 丁香婷婷在线 | 亚洲精品视频在线看 | 亚洲午夜久久久久久久久电影网 | 操操色 | 亚洲欧美日韩一二三区 | 国产在线精品一区二区三区 | 在线看的av网站 | 97成人在线 | 国产不卡精品 | 日韩在线| 天天曰天天射 | 国产精品毛片一区二区在线看 | 欧美精品v国产精品v日韩精品 | 808电影免费观看三年 | 91网页版免费观看 | 国产一级性生活视频 | 色a4yy| 曰韩在线| 成人精品一区二区三区中文字幕 | 狠狠色噜噜狠狠 | 操操操人人 | 精品国内自产拍在线观看视频 | 日韩在线视频在线观看 | 午夜精品一二三区 | 青青草在久久免费久久免费 | 亚洲视频精选 | 日日夜日日干 | 97狠狠干 | 久久在线免费观看 | 日韩视频一区二区三区在线播放免费观看 | 国产成人精品在线播放 | 波多野结衣综合网 | 成人毛片一区二区三区 | 久久综合狠狠综合久久狠狠色综合 | 成人精品电影 | 91插插插免费视频 | 成人一级黄色片 | 99久久www免费 | 久草在线最新视频 | 久久www免费人成看片高清 | 18国产精品白浆在线观看免费 | 性色va| 波多野结衣在线观看一区 | 九九热在线观看 | 99成人精品| 国产高清不卡 | 国产高清在线观看av | 夜夜骑天天操 | 91日韩在线专区 | 国产老太婆免费交性大片 | 日韩欧美在线一区二区 | 欧美一区二区三区在线播放 | 麻豆视频国产精品 | 精品久久久久久久久久岛国gif | 亚洲在线视频网站 | av在线电影网站 | av一级一片 | 中文字幕第一页av | 亚洲国产成人精品在线观看 | 免费av小说| 97精产国品一二三产区在线 | 天天射天天操天天干 | 不卡国产在线 | 在线电影日韩 | 久久超碰网 | 午夜久久精品 | 欧美最猛性xxxxx亚洲精品 | 成人四虎 | 在线视频中文字幕一区 | 亚洲人成影院在线 | 亚洲天堂精品视频 | 西西444www大胆高清视频 | 99精品免费在线观看 | 精品少妇一区二区三区在线 | 日韩视频一区二区三区 | av一区二区在线观看中文字幕 | 在线91av | 播五月婷婷 | 久久久久久久久久久久av | 天天干天天综合 | 欧美先锋影音 | 又黄又刺激又爽的视频 | 激情网站 | 国产成人亚洲精品自产在线 | 中文字幕在线日本 | 成人午夜黄色影院 | 久艹视频免费观看 | 中文字幕在线播放一区二区 | 九九热精品视频在线观看 | 国内精品美女在线观看 | 特片网久久 | 人人爽人人射 | 超碰人人在 | 国产青青青 | 97人人爽人人 | 欧美日韩二区在线 | 一本一本久久a久久精品牛牛影视 | 一区二区av | 国产尤物视频在线 | 欧美精品第一 | 久久99视频免费 | 亚洲精品永久免费视频 | 欧美日韩99 | 国产日韩欧美自拍 | 91精品久久久久久久99蜜桃 | 久久66热这里只有精品 | 国产精品久久久久久高潮 | 久久免费播放 | 日韩一二区在线观看 | 色五月成人 | 亚洲精品在线视频网站 | 国产99久久久精品视频 | 国产成人av在线 | 国产首页 | 久久艹欧美 | 99久久久国产精品 | 亚洲国产成人高清精品 | 久av电影| 国产日韩精品一区二区 | www.婷婷com| 久热免费在线观看 | 国产一级做a | 日韩一级电影在线观看 | 国产精品福利小视频 | 亚洲精品玖玖玖av在线看 | 国产a级精品 | 黄色大片日本 | 91黄色影视 | 日韩免费一级a毛片在线播放一级 | 手机在线看永久av片免费 | 在线中文字幕观看 | 午夜精品福利在线 | 国产精品igao视频网入口 | 香蕉在线视频播放网站 | 日日爱夜夜爱 | 亚洲伊人成综合网 | 97狠狠干| 免费观看91视频大全 | 久久精品欧美一 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 国产高清在线免费 | 91av官网| 五月开心六月婷婷 | 天天弄天天干 | a在线免费观看视频 | 天天操天天操天天操 | 国产超碰在线观看 | 在线观看欧美成人 | 91成人区 | 97超视频| 国产精品一区二区在线看 | 九九热免费视频在线观看 | 色综合夜色一区 | 五月婷婷开心中文字幕 | 91精彩在线视频 | 九九免费在线看完整版 | 欧美在线视频精品 | 激情丁香综合五月 | 久久精品国产美女 | 国产精品一区欧美 | 91福利国产在线观看 | 亚洲区另类春色综合小说校园片 | 国产免费黄视频在线观看 | 久久在现视频 | 黄色一级免费电影 | 精品国产乱码 | 亚洲视频在线观看免费 | 大胆欧美gogo免费视频一二区 | 婷婷.com| 这里只有精彩视频 | 热99在线 | 亚洲天天综合网 | 国产精品中文字幕在线播放 | 中文字幕日本在线 | 91在线播放综合 | 色88久久 | 公与妇乱理三级xxx 在线观看视频在线观看 | 一区av在线播放 |