日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

textmate开发一个blog

發(fā)布時(shí)間:2025/3/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 textmate开发一个blog 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
TextMate開發(fā)一個(gè)簡單的Blog吧。 1、首先安裝git,下載源碼編譯或者到這里下載package:[url]http://metastatic.org/text/Concern/2007/09/15/new-git-package-for-os-x/[/url] 2、在Terminal中鍵入如下命令: cd ~/Desktop git clone git://github.com/drnic/ruby-on-rails-tmbundle.git “Ruby on Rails.tmbundle“ cd “Ruby on Rails.tmbundle“ git checkout --track -b two_point_ooh origin/two_point_ooh git pull 3、雙擊桌面上的“Ruby on Rails.tmbundle“圖標(biāo)安裝此bundle 這樣,Ruby on Rails 2.0 的bundle就安裝到TextMate里面了 下面可以開始開發(fā)一個(gè)新的應(yīng)用了 在終端里輸入 Ruby代碼?
  • rails?blogcd?blogmate?.??
  • 增加一個(gè)模型 Ruby代碼?
  • ruby?script/generate?model?Post?subject:string?body:text??
  • 生成了一個(gè)新的遷移 001_create_posts.rb,包含一個(gè)方法 Create_Table Ruby代碼?
  • create_table?:posts?do?|t|??t.string?:subject??t.text?:body??t.timestampsend??
  • Sexy Migration的支持 把光標(biāo)放在 t.text :body下面一行,輸入 t. 然后按下?(Tab鍵),選擇“Create boolean column”?或者按下0?,創(chuàng)建一個(gè)布爾字段,然后輸入 published,如果按下Tab鍵沒有反應(yīng),看看是否選擇對了Ruby on Rails的bundle(在底下狀態(tài)欄里) 請注意這個(gè)時(shí)候下面還有一行t. 如果需要繼續(xù)輸入其他字段,就可以再按下Tab鍵直接輸入。 我們現(xiàn)在不需要?jiǎng)e的更多的字段了,就按下??K(Control+Shift+K)把這一行刪除。然后保存文件?S 然后運(yùn)行遷移,可以在命令行輸入 Ruby代碼?
  • rake?db:migrate??
  • 或者直接在編輯器里按下??|(Control+|),選擇“Migrate to Current”。 Post Fixtures 修改一下test/fixtures/post.yml Ruby代碼?
  • published:??subject:?Some?article??body:?A?test?article??published:?truenonpublished:??body:?Still?writing?this?one??
  • 在Rails2.0里,fixtures不再使用id了,后面我們可以看到怎么使用foxy fixtures來自動(dòng)關(guān)聯(lián)。 Public blog controller 創(chuàng)建一個(gè)控制器,可以通過命令行 Ruby代碼?
  • ruby?script/generate?controller?blog??
  • 或者直接在編輯器里按下?|(Control+|),選擇“Call Generate Script”,再選擇“Controller”,給它起個(gè)名字叫做blog,action里不要設(shè)置任何內(nèi)容。 現(xiàn)在打開blog_controller_test.rb,要快速找到文件,可以按下??T,然后輸入bct就可以找到了。 可以看到,功能性的測試是非常清楚和簡單的。 讓我們開始TDD吧,先刪除?test_truth?方法 然后創(chuàng)建一個(gè)測試來顯示blog文章列表 輸入deftg 然后按下Tab鍵 自動(dòng)生成了以下代碼 Ruby代碼?
  • def?test_should_get_action??@model?=?models(:fixture_name)??get?:action,?:id?=>?@model.to_param??assert_response?:successend??
  • 光標(biāo)停留在action上,用index代替它,然后按下Tab鍵,光標(biāo)選擇了方法的第一行,刪除它,然后按三次Tab鍵,刪除:id => @model.to_param?部分。再次按下Tab鍵,光標(biāo)跳到方法的最后一行。現(xiàn)在的代碼應(yīng)該是這樣的: Ruby代碼?
  • def?test_should_get_index??get?:index??assert_response?:successend??
  • 鍵入 asg ,然后按下Tab鍵,然后鍵入posts,然后按下Tab鍵。 下面,鍵入ass ,然后按下Tab鍵,輸入div#posts,按下Tab鍵,刪除余下的部分。然后連續(xù)按Tab鍵兩次,把光標(biāo)放在assert_select里面,現(xiàn)在代碼如下 Ruby代碼?
  • assert_select?'div#posts'?doend??
  • 鍵入ass,按下Tab鍵,鍵入div.post,然后按下Tab兩次,鍵入count,取代掉text。 現(xiàn)在再按下Tab鍵,鍵入post.size,最后一次按下Tab鍵,刪除被選中的部分。 好了,現(xiàn)在我們的測試方法完成了 Ruby代碼?
  • def?test_should_get_index??get?:index??assert_response?:success??assert(posts?=?assigns(:posts),?“Cannot?find?@posts“)??assert_select?'div#posts'?do????assert_select?'div.post',?:count?=>?posts.size??endend??
  • 還有一個(gè)deftp代碼片段來創(chuàng)建一個(gè)POST方法的測試。很容易記住的,deftg代表define test get, deftp代表define test post Controller actions 要導(dǎo)航到blog_controller.rb文件,有三種選擇: 1,按下???↓(Shift+option+command+下箭頭),然后在彈出的菜單中選擇“Controller”, 2,按下??↓(option+command+下箭頭),然后直接去controller文件(來回切換) 3,按下?T,然后鍵入bc,找到那個(gè)文件。 增加一個(gè)index方法 Ruby代碼?
  • def?index??@posts?=?Post.find_all_by_published(true)end??
  • Action Views 要?jiǎng)?chuàng)建或者導(dǎo)航到一個(gè)視圖,可以按下???↓(shift+option+command+下箭頭),然后選擇“View”(就像上面那樣),或者按下??↓(option+command+下箭頭)來切換控制器的方法和對應(yīng)的視圖。 因?yàn)闆]有對應(yīng)的app/views/blog/index*文件,所以會(huì)提示要求創(chuàng)建一個(gè)空白視圖,默認(rèn)的它會(huì)猜測文件名稱為index.html.erb?因?yàn)榉椒ǖ拿纸凶?span style="font-family:Monaco;font-size:12px;line-height:normal;">index,但是當(dāng)然您可以改為其他名字。 如果您得到一個(gè)提示:blog_controller.rb does not have a view,請注意先要保存控制器文件,然后在切換到視圖。同時(shí)請注意,光標(biāo)要在控制器方法的范圍內(nèi),才能起作用。 好了,我們轉(zhuǎn)到剛創(chuàng)建的index.html.erb 鍵入div,然后按兩次Tab,把id改為post,然后再按Tab,應(yīng)該是這樣: <div id=“posts“> </div> 在div標(biāo)簽中,鍵入for,按下Tab,生成一個(gè)for循環(huán),在光標(biāo)處替換list為@posts,按下Tab,然后鍵入post,替換掉item,再按下Tab,現(xiàn)在光標(biāo)應(yīng)該在for循環(huán)里面了。 鍵入div,然后Tab,生成了div標(biāo)簽,刪除id,鍵入class='post',再按Tab,進(jìn)入了div標(biāo)簽里面。 用control+>創(chuàng)建一個(gè)<%= %>, 如果再按一下control+>,就會(huì)生成<% %>,再按一下,會(huì)生成<%- -%>,再按一下就會(huì)生成<%# %>,如此循環(huán)往復(fù)。 鍵入post.body 實(shí) 際上,我們還需要顯示標(biāo)題,所以在<%= post.body %>這一行上面(按下command+return,上箭頭),鍵入h3,然后按下control+<,生成<h3>標(biāo)簽。鍵入 control+>,鍵入post.subject 在下面的 <% else %><% end %> 中間,創(chuàng)建一個(gè)簡單的標(biāo)記<p></p>(使用control+<),鍵入There are no posts available to read. All y'all come back soon, yer hear.? 呵呵,純粹好玩兒。 好了,我們的視圖現(xiàn)在是這樣子了: Ruby代碼?
  • <div?id=“posts“>??<%?if?!@posts.blank??%>????<%?for?post?in?@posts?%>??????<div?class=“post“>????????<h3><%=?post.subject?%></h3>????????<%=?post.body?%>??????</div>????<%?end?%>??<%?else?%>????<p>There?are?no?posts?available?to?read.?All?y'all?come?back?soon,?yer?hear.</p>??<%?end?%></div>??
  • 現(xiàn)在可以運(yùn)行單元測試了,應(yīng)該可以通過。可以在命令行中輸入:rake test:functionals ? 或者直接在編輯器里鍵入control+\然后選擇2:Test Functionals 我們現(xiàn)在還不能讓用戶留言。 Foxy Fixtures 創(chuàng)建一個(gè)comment模型 ruby script/generate model Comment body:text name:string post:references 請注意,這里post:references的作用和以前的post_id:integer是一樣的。在生成的遷移文件中,它創(chuàng)建了t.reference :post 下面是生成的第二個(gè)遷移文件 Ruby代碼?
  • create_table?:comments?do?|t|??t.text?:body??t.string?:name??t.references?:post??t.timestampsend??
  • 運(yùn)行這個(gè)遷移。命令行里鍵入 rake db:migrate , 或直接在編輯器按下control+| 然后在彈出的菜單重選擇Migrate to Current 下面,我們創(chuàng)建幾個(gè)comment fixtures,以便我們看看Foxy Fixtures怎么運(yùn)行的。 打開test/fixtures/comments.yml: Ruby代碼?
  • one:??body:?MyText??name:?MyString??post:two:??body:?MyText??name:?MyString??post:??
  • 字段post替代了rails1.2中post_id的位置。 上面我們有了published和nonpublished,或許很難記住,我們有一個(gè)快捷鍵。 把光標(biāo)放在post: 后面,然后按下 option+Esc , 就可以選擇了。 關(guān)聯(lián) 為了能夠用到Foxy Fixtures,我們必須增加兩個(gè)模型類之間的關(guān)聯(lián)。 現(xiàn)在你已經(jīng)可以快速切換到模型類的文件了,(shift+option+command+下箭頭)在comment.rb 模型類文件中,鍵入bt然后按下Tab鍵,鍵入post Ruby代碼?
  • belongs_to?:post,?:class_name?=>?“Post“,?:foreign_key?=>?“post_id“??
  • 現(xiàn)在:class_name和:foreign_key都已經(jīng)一起自動(dòng)的把object改為post了,當(dāng)然,您繼續(xù)按下Tab鍵,還可以繼續(xù)改。不過我們這里就不需要了,直接刪除后面的就行了。 現(xiàn)在它是這樣的: Ruby代碼?
  • class?Comment?<?ActiveRecord::Base??belongs_to?:postend??
  • 然后去看看post類,打開Post.rb 鍵入hm,然后Tab。 同樣的我們不需要那些option,刪除。 Ruby代碼?
  • class?Post?<?ActiveRecord::Base??has_many?:commentsend??
  • 如果您需要has_many :through ,可以鍵入hmt然后tab,就行了。 最后我們測試一下。(control+\) 路由 打開路由文件routes.rb 修改一下: Ruby代碼?
  • ActionController::Routing::Routes.draw?do?|map|??map.resources?:posts??map.connect?':controller/:action/:id'??map.connect?':controller/:action/:id.:format'end??
  • 創(chuàng)建文章 從Post模型文件post.rb,您可以快速導(dǎo)航到同名的控制器文件,可以支持單數(shù)形式的控制器名或者復(fù)數(shù)形式的控制器名稱,但是默認(rèn)都是復(fù)數(shù)形式的,以更加符合REST風(fēng)格。 要 創(chuàng)建一個(gè)PostsController,可以使用Go To...的快捷鍵shift+option+command+下箭頭,然后選擇Controller,因?yàn)闆]有post_controller.rb或 者posts_controller.rb,所以會(huì)問您是否需要?jiǎng)?chuàng)建一個(gè),確認(rèn)后,就得到我們自己的posts_controller.rb文件了。 注意,我們通常也可以使用腳手架來自動(dòng)生成控制器文件,包括路由和測試文件。 在posts_controller里面,我們先要?jiǎng)?chuàng)建一個(gè)控制器類。 如果posts_controller.rb里面有內(nèi)容,清空全部的內(nèi)容,然后鍵入cla,按下Tab,選擇Create controller class,在光標(biāo)處鍵入Posts,然后tab,然后鍵入post,然后tab,最后鍵入Post,然后tab,光標(biāo)回到了類的中間。 Ruby代碼?
  • class?PostsController?<?ApplicationController??before_filter?:find_post??private??def?find_post????@post?=?Post.find(params[:id])?if?params[:id]??endend??
  • TDD測試PostsController 當(dāng)前是沒有一個(gè)PostsController的功能測試的,我們可以繼續(xù)使用GoTo...的快捷鍵:shift+option+command+下箭頭,然后選擇Functional Test,就會(huì)創(chuàng)建一個(gè)控制器測試文件 然后分別為index, new, edit三個(gè)方法建立測試,使用deftg+Tab的方式。 要建立create方法的測試,請鍵入deftp,然后按下Tab,鍵入create,然后tab,鍵入post,然后tab,按下delete鍵,再tab,再delete,再Tab,光標(biāo)就轉(zhuǎn)移到{}中,然后修改成下面這樣: Ruby代碼?
  • def?test_should_post_create??post?:create,?:post?=>?{?:subject?=>?'Test',?:body?=>?'Some?body',?:published?=>?'1'?}??assert_response?:redirectend??
  • 在assert_response這一行后面,我們可以測試我們想跳轉(zhuǎn)重定向的位置。 如果您鍵入art,就會(huì)創(chuàng)建一個(gè):assert_redirected_to :action => “index“??代碼片段 現(xiàn)在增加了好幾個(gè)assert_redirected_to的代碼片段,使用到了資源化路由( resourceful route)
    • artp –?assert_redirected_to model_path(@model)
    • artpp –?assert_redirected_to models_path
    • artnp –?assert_redirected_to parent_child_path(@parent, @child)
    • artnpp –?assert_redirected_to parent_child_path(@parent)
    鍵入artpp,然后按下Tab,然后鍵入post,這樣生成的斷言就會(huì)要求create動(dòng)作重定向到index頁面 最后的test_should_post_create方法應(yīng)該是這樣的: Ruby代碼?
  • def?test_should_post_create??post?:create,?:post?=>?{?:subject?=>?'Test',?:body?=>?'Some?body',?:published?=>?'1'?}??assert_response?:redirect??assert_redirected_to?posts_pathend??
  • 然后運(yùn)行測試,然后可以看到這些新創(chuàng)建的測試都沒通過 視圖 現(xiàn)在回到posts_controller.rb文件(option+command+下箭頭) 我們要?jiǎng)?chuàng)建三個(gè)新的方法:index, new, edit。新方法可以這樣來創(chuàng)建:鍵入def,??,?index,??,?@posts = Post.fina,??,??. 現(xiàn)在這三個(gè)方法分別需要三個(gè)視圖模板來對應(yīng)。 把光標(biāo)放在index方法中,呼叫出Goto...菜單(shift+option+command+下箭頭),選擇View,會(huì)創(chuàng)建一個(gè)新的index.html.erb模板, 讓我們來創(chuàng)建一個(gè)表格來顯示Posts吧 鍵入table,按下control+<,生成table標(biāo)簽。 然后在table標(biāo)簽中生成tbody標(biāo)簽 在tbody里,我們希望可以枚舉 @posts ,每一行一條記錄。 按三次control+>, 創(chuàng)建<%- -%>,在里面鍵入?@posts.each do |post| 轉(zhuǎn)到下一行(command+enter),鍵入end, 按下Tab,生成<% end -%>,這樣我們在這個(gè)erb模板中就有了一個(gè)ruby的代碼塊了。 在這個(gè)代碼塊中,生成tr和td,我們把post的標(biāo)題放在這個(gè)單元格里。 鍵入 post.subject,選中,然后按下control+>,生成<%= post.subject %>. 最后形成這樣子: Ruby代碼?
  • <table>??<tbody>????<%-?@posts.each?do?|post|?-%>??????<tr>????????<td><%=?post.subject?%></td>??????</tr>????<%?end?-%>??</tbody></table>??
  • Forms 把光標(biāo)放在Controller的new方法中,按下shift+option+command+下箭頭,叫出Goto菜單,選擇View,生成new.html.erb 在新的new.html.erb文件中,鍵入ffe,然后tab,鍵入post,然后tab兩次 有兩個(gè)snippet可以生成form_for: ff和ffe,唯一的區(qū)別就是ff生成的代碼沒有error_messages_for那部分內(nèi)容 然后我們需要為subject屬性增加一個(gè)標(biāo)簽和文本框: 首先生成一個(gè)p標(biāo)簽(control+<,然后tab),鍵入f. 然后tab,選擇Label,把默認(rèn)的改為subject,然后tab, 刪除剩下的。 接著創(chuàng)建一個(gè)<br>標(biāo)簽(control+entern),鍵入f.然后tab,選擇TextField,鍵入subject 現(xiàn)在重復(fù)創(chuàng)建body和published兩個(gè)文本域 請注意,published這個(gè)屬性的標(biāo)簽最好用published yet?,你可以tab進(jìn)默認(rèn)的字符串替換掉。 最后用f. snippet增加一個(gè)submit按鈕 啟動(dòng)script/server,然后訪問[url]http://localhost:3000/posts/new[/url] 最后的form代碼如下: Ruby代碼?
  • <%=?error_messages_for?:post?%><%?form_for?@post?do?|f|?-%>??<p>????<%=?f.label?:subject?%><br?/>????<%=?f.text_field?:subject?%>??</p>??<p>????<%=?f.label?:body?%><br?/>????<%=?f.text_area?:body?%>??</p>??<p>????<%=?f.label?:published,?“Published?yet?“?%><br?/>????<%=?f.check_box?:published?%>??</p>??<p>????<%=?f.submit?“Submit“?%>??</p><%?end?-%>??
  • 值得說明的是:如果您按下control+enter生成了br標(biāo)簽,但不是<br />,而你希望更加符合xhtml的規(guī)范,請轉(zhuǎn)到TextMatepreferences,選擇advanced標(biāo)簽,選中“Shell Variablees”,增加一個(gè)變量叫做TM_XHTML,值是 / Partials 剛才我們創(chuàng)建的這個(gè)form和edit.html.erb模板所需要的form是一模一樣的,除了復(fù)制/粘帖的方法以外,我們還可以創(chuàng)建一個(gè)局部模板,減少不必要的重復(fù)。 全部選中form(command+A),然后按下control+shift+H,會(huì)出來一個(gè)對話框,我們給他一個(gè)名字叫做form,然后確定。 可以看到自動(dòng)生成了一個(gè)名叫_form.html.erb的文件,剛才的form都在這個(gè)_form.html.erb文件中,而new.html.erb的內(nèi)容被一個(gè)語句代替: <%= render :partial => 'form' %> 然后我們創(chuàng)建edit.html.erb:? 回到控制器文件,把光標(biāo)放在edit方法上,按下shift+option+command+下箭頭, 就自動(dòng)生成了edit.html.erb,把剛才上面的語句粘帖到空白文件中。 Link Helpers 在new.html.erb底下我們還想創(chuàng)建一個(gè)新的返回全部文章列表的鏈接。在post控制器,而不是在blog控制器噢。其實(shí)就是調(diào)用index方法,通過resources rout: posts_path 下面這些link_to是支持resources route的:
    • lip –?<%= link_to “l(fā)ink text...“, model_path(@model) %>
    • lipp –?<%= link_to “l(fā)ink text...“, models_path %>
    • linp –?<%= link_to “l(fā)ink text...“, parent_child_path(@parent, @child) %>
    • linpp –?<%= link_to “l(fā)ink text...“, parent_child_path(@parent) %>
    • lim –?<%= link_to model.name, model_path(model) %>
    鍵入lipp,然后tab,鍵入Show all posts,然后tab兩次,鍵入post (經(jīng)過測試,lipp好像有些問題,不能生成相應(yīng)的代碼,可以在Bundle Editor里面選擇Edit Snippets... ,把lipp的snippet改為: ${TM_TEMPLATE_START_RUBY_EXPR}link_to ${1:“${2:link text...}“}, ${10:model}s_path${TM_TEMPLATE_END_RUBY_EXPR} 這樣就好了) Controllers: response_to 和 redirect_to 現(xiàn)在我們在posts_controller.rb里面加上 create方法。先去訪問文件(option+command+下箭頭) 在edit方法下面,鍵入def,然后tab,然后鍵入create,然后tab。然后在create方法中填充下面的內(nèi)容 Ruby代碼?
  • def?create??@post?=?Post.new(params[:post])??if?@post.save??else??endend??
  • 把光標(biāo)放在else上面,鍵入repp,然后tab2次。用post代替選中的文字。 redirect_to也有很多變化
    • rep –?redirect_to(model_path(@model))
    • repp –?redirect_to(models_path)
    • renp –?redirect_to(parent_child_path(@parent, @child))
    • renpp –?redirect_to(parent_child_path(@parent))
    在if語句條件為假的部分,我們演示一下respond_to 代碼塊。有兩個(gè)方法生成respond_to代碼塊: 鍵入rest,然后tab,生成 Ruby代碼?
  • respond_to?do?|wants|??wants.html?{??}end??
  • 然后按兩次tab,光標(biāo)置入wants.html{}里面,鍵入ra,然后tab,然后鍵入new。最終代碼如下: Ruby代碼?
  • respond_to?do?|wants|??wants.html?{?render?:action?=>?“new“?}end??
  • 另一個(gè),可以使用“升級”了的快捷鍵(shift+command+H),可以把選中的代碼轉(zhuǎn)換到respond_to代碼塊里。 選中if語句條件為真部分的respond_to整行(shift+command+L)然后按shift+command+H,光標(biāo)停在js上,刪除這一行(control+shift+K),最終代碼變成: Ruby代碼?
  • def?create??@post?=?Post.new(params[:post])??if?@post.save????respond_to?do?|wants|??????wants.html?do????????redirect_to(posts_path)??????end????end??else????respond_to?do?|wants|??????wants.html?{?render?:action?=>?“new“?}????end??endend??

  • 現(xiàn)在我們可以在[url]http://localhost:3000/posts/new[/url] 添加新的文章,并且在[url]http://loclahost:3000/blog[/url] 查看文章了。 還有一些遷移工作 我們還有一些附加工作, 把comments表的name列改名為author 在comments表中增加一個(gè)author_url字段 在comments表中的post_id字段增加一個(gè)索引 讓我們嘗試在一個(gè)遷移文件中做這些事情。 啟動(dòng)快速遷移(shift+control+M),給我們的遷移起個(gè)名字叫做ModifyComments,自動(dòng)生成了003_Modify_comments.rb并打開,光標(biāo)放在了mtab后面,刪除它,鍵入mcol,然后tab,選擇Rename / Rename Column?(3),鍵入comments???name???author????. 同樣我們再次鍵入mcol,然后tab,選擇Add / Remove Column(1),鍵入comments?author_url,然后?兩次。 現(xiàn)在鍵入mind,然后?,選擇Choose?Add / Remove Index(1),鍵入comments?post_id. ? 最終的代碼如下: class ModifyComments < ActiveRecord::Migration def self.up rename_column :comments, :name, :author add_column :comments, :author_url, :string add_index :comments, :post_id end def self.down remove_index :comments, :post_id remove_column :comments, :author_url rename_column :comments, :author, :name end end 請注意,down方法的順序是和up方法的順序相反的。 保存并執(zhí)行這個(gè)遷移 要記住修改comments的fixture文件。先打開文件(command+T,鍵入cy,回車),把name字段改名為author字段,并在每一節(jié)增加author_url,然后測試,應(yīng)該都順利通過。 此外,我們希望當(dāng)一篇文章發(fā)表時(shí)我們可以被通知到,為了做到這一點(diǎn),我們需要做以下的修改: 當(dāng)文章發(fā)布時(shí),有一個(gè)時(shí)間日期published date可以跟蹤; 移除published這個(gè)字段,因?yàn)槭欠褚呀?jīng)發(fā)布我們可以看published date。 開始快速遷移(shift+control+M),起個(gè)名字叫做?AddPublishedAtForPosts?一個(gè)新的遷移文件004_add_published_at_for_posts.rb,光標(biāo)還是在mtab后面,一樣,我們把mtab刪除,鍵入mcol,然后tab,在彈出來的菜單上選擇Add / Remove Column?(1),?鍵入posts??published_at???datetime???enter 再次鍵入mcoltab,然后選擇Remove / Add Column5),鍵入posts???published,然后tab兩次。 最終代碼如下: class AddPublishedAtForPosts < ActiveRecord::Migration def self.up add_column :posts, :published_at, :datetime remove_column :posts, :published end def self.down add_column :posts, :published, :boolean remove_column :posts, :published_at end end Remove/Add Column命令自動(dòng)在down方法中決定published字段為布爾字段,這取決于當(dāng)前數(shù)據(jù)庫db/schema.rb文件的狀態(tài)。 然后保存并執(zhí)行遷移。 現(xiàn)在我們要修改posts fixture文件。選擇posts.yml文件(command+T, 鍵入pyml,選擇posts.yml)。用published_at: 2008-01-01代替published: true?修改posts功能測試,首先先打開測試文件( shift+option+command+下箭頭,選擇Go to functional Test),用:published_at => Date.new(2008, 1, 1)?替換?:published => '1'. 修改post模型,打開posts.rbshift+option+command+下箭頭,選擇Go to Model), 黏貼下面的代碼: class Post < ActiveRecord::Base has_many :comments def published !self.published_at.nil? end def published=(publish) if publish self.published_at = DateTime.now if self.published_at.nil? else self.published_at = nil end end end 修改blog_controller.rb,用Post.find(:all, :conditions => “published_at IS NOT NULL“)代替Post.find_all_by_published(true)。然后測試運(yùn)行,所有的測試都應(yīng)該通過。 這篇文章的原文在ruby on rails bundle的幫助里,在TextMate里面打開rails項(xiàng)目的一個(gè)rb文件,使用快捷鍵Control+H,然后選擇2,就可以看到這篇文章了。最新的ror bundle更新于上個(gè)月底,還是很具有參考價(jià)值的,對于如何快速使用TextMate進(jìn)行rails開發(fā)是一個(gè)不錯(cuò)的教程。

    不過還有一些沒完成。不是特別完整。但是基本的快捷鍵都包含在里面了。
    ---------英文原版教程
    Step-by-step demonstration

    Get Version

    1.90.0??
    In this demo we’ll create a blog; because that’s what blogs are for: being demonstrations of web frameworks.

    The demonstration uses new features of Rails 2.0 and the snippets in this bundle.

    A New App

    rails blog
    cd blog
    mate .
    Add some models

    ruby script/generate model Post subject:string body:text
    This creates a 001_create_posts migration with a create_table:

    create_table :posts do |t|
    ? t.string :subject
    ? t.text :body

    ? t.timestamps
    end
    Sexy Migration support

    If you put the cursor on the line after t.text :body, type t. and press ?. Select “Create boolean column” (by pressing 0), and type “published” into the template field. If nothing happened when you pressed ?, check that when you opened the migrations file you’ve selected the bundle “Ruby on Rails”.

    Note that another t. was created on the next line! Press ? and the cursor will be placed after it. You can now press ? again to create another column, or delete this line.

    Here, delete the extraneous t. line (? ? K). And save the file (? S).

    Run the migrations, either from the prompt:

    rake db:migrate
    or directly from the editor with ? | (Ctrl-Pipeline), and choosing option “Migrate to Current”.

    Post fixtures

    Update the test/fixtures/posts.yml file as:

    published:
    ? subject: Some article
    ? body: A test article
    ? published: true

    nonpublished:
    ? body: Still writing this one
    Note, in Rails 2.0 fixtures no longer have explicit ids. Later on we’ll look at snippets for using Foxy Fixtures with auto-completion for associations.

    Public blog controller

    Create a controller for our blog, either via the command prompt:

    ruby script/generate controller blog
    or directly from the editor with ? |, and choosing option “Call Generate Script”, choose “Controller”, give it the name “blog”, and empty the list of actions.

    Now open blog_controller_test.rb. To find this file quickly press ? T, type bct, and select the file.

    Note how much cleaner functional tests are now via ActionController::TestCase.

    Let’s do some TDD. First, delete the test_truth dummy method.

    To create a test to show a list of blog articles:

    deftg
    and ? gives:

    def test_should_get_action
    ? @model = models(:fixture_name)
    ? get :action, :id => @model.to_param
    ? assert_response :success

    end
    Type index to replace action. Press ?, and then ? to remove the first line, then press ? three times and then ? to remove the :id => @model.to_param part. The press ? again to go to the end of the method. Now we have:

    def test_should_get_index
    ? get :index
    ? assert_response :success

    end
    Now type asg, press ?, and type posts, and press ? again. This creates an instance variable lookup within an assertion:

    assert(posts = assigns(:posts), "Cannot find @posts")
    Now, let’s assert the HTML format.

    Type ass and press ?. Type div#posts, press ? and ?, then ? twice to place the cursor within the assert_select block:

    assert_select 'div#posts' do

    end
    Now we’ll check that the @posts objects are represented in the div#posts element.

    With the cursor inside the assert_select:

    Type ass, press ?, type div.post, press ? twice, and type count (to replace the text). Now press ? again, and type posts.size. Press ? a final time (it will highlight the do...end block), and press ?.

    Our test method is now finished:

    def test_should_get_index
    ? get :index
    ? assert_response :success
    ? assert(posts = assigns(:posts), "Cannot find @posts")
    ? assert_select 'div#posts' do
    ??? assert_select 'div.post', :count => posts.size
    ? end
    end
    NOTE: there is also a deftp snippet for functional tests to create a POST test stub. To memorize: deftg stands for define test get and deftp stands for define test post

    Controller actions

    To navigate to blog_controller.rb there are three options:

    press ? ? ? ↓, and select “Controller” from the drop-down list
    press ? ? ↓ and you’ll go directly to the controller (toggles between the two files)
    press ? T, type bc, choose the file, press ?.
    Add the index action method:

    def index
    ? @posts = Post.find_all_by_published(true)
    end
    Action views

    To create/navigate to the view, press ? ? ? ↓ and select “View” (like above). Or press ? ? ↓ to toggle between a controller method and it’s view.

    As there are no app/views/blog/index* files, it will prompt you to create a blank view file. By default it guesses index.html.erb (because the method was named index), but of course you can change that in the dialog box.

    If instead you got the message “blog_controller.rb does not have a view”, note that you first need to save the controller file before hitting ? ? ? ↓ or ? ? ↓. Also note that the cursor must be within the scope of a method for ? ? ? ↓ or ? ? ↓ to work.

    Press enter to accept index.html.erb. You are taken to the new file.

    Let’s create HTML to match the earlier tests.

    Type div and press ? twice, then type posts and press ?:

    <div id="posts">

    </div>
    Inside the div element, type for and press ?. This expands into a large ERb-enabled for-loop. Type @posts, press ?, type post and press ?. The cursor is now inside the for-loop.

    Inside the for-loop, type: div and press ?. Press ?, and type? class='post' and press ? to enter the div element.

    Create a <%=? %> element (? >). If you press ? > again, it toggles to <%? %>, and then again and it becomes <%-? -%>, and again and it becomes <%#? %> (a Ruby comment). Pressing ? > again starts at <%=? %> again.

    Enter post.body within the ERb template field.

    Actually, we’ll need to show the subject too, so above the <%= post.body %> line (press ↑ followed by ? ?) type ‘h3’, and press ? < (LessThan), then ? > (GreatherThan), and post.subject.

    The resulting line is: <h3><%= post.subject %></h3>

    Move the cursor down between <% else %> and <% end %>.

    Create a simple element <p></p> (? ? W or ? <). You can change the element type here. Just press ? to go inside the element. Type There are no posts available to read. All y'all come back soon, yer hear. because its funny.

    Our index.html.erb template is now:

    <div id="posts">
    ? <% if !@posts.blank? %>
    ??? <% for post in @posts %>
    ????? <div class="post">
    ??????? <h3><%= post.subject %></h3>
    ??????? <%= post.body %>
    ????? </div>
    ??? <% end %>
    ? <% else %>
    ??? <p>There are no posts available to read. All y'all come back soon, yer hear.</p>
    ? <% end %>

    </div>
    If we run our functional tests they now pass: run either from the command prompt with rake test:functionals or directly from the editor by pressing ? \ and press 2 for “Test Functionals”

    As yet, we have no way for users to leave comments.

    Foxy Fixtures

    Create a comment model:

    ruby script/generate model Comment body:text name:string post:references
    Note: here post:references is effectively the same as post_id:integer. Within the generated migration it creates t.reference :post. There is also a t. and tcr snippet for references, as for other standard datatypes, which helps setup polymorphic associations.

    The generated create_table in 002_create_comments.rb is:

    create_table :comments do |t|
    ? t.text :body
    ? t.string :name
    ? t.references :post

    ? t.timestamps
    end
    Run rake db:migrate, or directly from the editor with ? | and choose option “Migrate to Current”.

    Now create some comment fixtures so we can look at Foxy Fixtures. Open text/fixtures/comments.yml (? T, type cy, press ?).

    By default, the generated comments.yml starts like:

    one:
    ? body: MyText
    ? name: MyString
    ? post:

    two:
    ? body: MyText
    ? name: MyString
    ? post:
    The post fields replace the rails1.2 post_id fields. Now, we can specify the post.yml labels for a post. From above we have published and unpublished. It can be hard to remember what fixtures we have, so there is a key-combo helper.

    Put the cursor after post: and press ? ?. A drop-down box appears with the names of the posts.yml fixtures. Select published and press ?. Repeat for the 2nd fixture. This gives us:

    one:
    ? body: MyText
    ? name: MyString
    ? post: published

    two:
    ? body: MyText
    ? name: MyString
    ? post: published
    Associations

    To enable the Foxy Fixtures, we need to add associations to the model classes.

    You can now quickly go from a fixtures file (we’re in comments.yml) to the model file (? ? ? ↓).

    Within comment.rb model, create a new line within the class, and type bt and press ?. Type post. This creates a snippet:

    belongs_to :post, :class_name => "Post", :foreign_key => "post_id"
    The class name and foreign key are now generated from the association name. You can change them by tabbing across. But, we only need the default, so we can delete these options.

    Press ? and ? to remove the :class_name and :foreign_key options. The Comment class is now:

    class Comment < ActiveRecord::Base
    ? belongs_to :post
    end
    Now go to the Post class. Press ? T and type post and select the model file, and press ?.

    Create a new line within the Post class (? ?). Type hm and press ? to generate a has_many association. Type comment, and the resulting snippet is:

    has_many :comments, :class_name => "comment", :foreign_key => "class_name_id"
    We don’t need the options. So press ? once and then ?.

    class Post < ActiveRecord::Base
    ? has_many :comments
    end
    Note: there is also a has_many :through snippet. Type hmt and ? to activate it.

    Finally, we can run our tests since adding the Comment model + fixtures (? \).

    rake test
    Routes

    Open the routes file (? T, type routes and press ?).

    Change the routes file to:

    ActionController::Routing::Routes.draw do |map|
    ? map.resources :posts
    ? map.connect ':controller/:action/:id'
    ? map.connect ':controller/:action/:id.:format'
    end
    Creating Posts

    From the Post model class (post.rb) you can now quickly navigate to a controller of the same name. It supports either singular or plural controller names, but will default to the plural name, which is the REST/resources preferred name.

    To create a PostsController, use the ‘Go To’ hot key (as above) ? ? ? ↓ and select ‘Controller’. As there is no post_controller.rb nor posts_controller.rb it will create a posts_controller.rb controller file; which is what we want here.

    Note; at this stage you could use the Rails 2.0 scaffold generator to create the posts_controller.rb (and tests and routes).

    In the blank file, we need to create a controller class.

    Type cla and ?, and select “Create controller class”. Type Posts and ?, post and ?, and finally, Post and ?. This leaves the cursor in the middle of the generated class:
    class PostsController < ApplicationController
    ? before_filter :find_post



    ? private
    ? def find_post
    ??? @post = Post.find(params[:id]) if params[:id]
    ? end
    end
    TDD for Posts controller

    Currently there is not a functional test for our posts_controller.rb. To create it, use the ‘Go To’ hot key (? ? ? ↓) and select ‘Functional Test’. This will create a blank file.

    Type cla and ?, and select “Create functional test class”. Type Posts and ?. (The functional test class name should match the controller class, with Test suffixed to it).

    The functional test class snippet gives you a deft stub. If you press ? now, it creates a generic test method snippet:

    def test_case_name

    end
    Instead, we will use the deftg (GET request) and deftp (POST request) snippets.

    Create a test for the index, new and edit actions. For index and new, we can delete the @model = models(:fixture_name), etc parts.

    To test for the create action, type deftp and ?. Type create and ?, type post and ?, type ? and ?, and again ? and ?. Now enter in a hash of the values to pass in for the test, say :subject => 'Test', :body => 'Some body', :published => '1'. The result should look like:

    def test_should_post_create
    ? post :create, :post => { :subject => 'Test', :body => 'Some body', :published => '1' }
    ? assert_response :redirect

    end
    On the line after the assert_response expression, we’ll test for where we want to be redirected to.

    If you type art you create an old-style assert_redirected_to :action => "index" snippet.

    In addition there are now various assert_redirected_to snippets that use resourceful routes:

    artp – assert_redirected_to model_path(@model)
    artpp – assert_redirected_to models_path
    artnp – assert_redirected_to parent_child_path(@parent, @child)
    artnpp – assert_redirected_to parent_child_path(@parent)
    As we’ll see later, this naming scheme is used for other snippets that use resourceful routes, like link_to and redirect_to.

    Type artpp and ?, and type post, to assert that the create action must redirect to the index page.

    The final test_should_post_create method is:

    def test_should_post_create
    ? post :create, :post => { :subject => 'Test', :body => 'Some body', :published => '1' }
    ? assert_response :redirect
    ? assert_redirected_to posts_path
    end
    Running our tests (rake test:functionals or ? \) shows all these new tests failing.

    Views

    Go back to the posts_controller.rb file (? ? ↓).

    Now add three actions – index, new and edit. New methods can be created with the def snippet:

    class PostsController < ApplicationController
    ? before_filter :find_post

    ? def index
    ??? @posts = Post.find(:all)
    ? end

    ? def new
    ??? @post = Post.new
    ? end

    ? def edit
    ? end

    ? private
    ? def find_post
    ??? @post = Post.find(params[:id]) if params[:id]
    ? end
    end
    Note: the index method could be created by typing def, ?, index, ?,? @posts = Post.fina, ?, ?.

    Now we need templates for the index, new and edit actions.

    Place the cursor inside the index method, and use the ‘Go To’ hot key (? ? ? ↓) and select ‘View’. A dialog box will pop up asking for the name of the new template (as there are no app/views/posts/index* files). By default, the suffix is now .html.erb rather than the old .rhtml. Press ?, to accept index.html.erb as your template name.

    Let’s just create a simple table showing the Posts.

    Type table and ? < to generate <table></table>, and press ? to put the tags on separate lines.

    Do the same to create a <tbody></tbody> element.

    Inside the <tbody></tbody> we want to iterate over the @posts, one per <tr></tr> row.

    Press ? >, three times, to create a <%- -%> tag. Inside it type @posts.each do |post|.

    On the next line (? ?), type end and ?, to create <% end -%>. We now have a Ruby block within this ERb template.

    Inside the block, create a <tr></tr> element, and within it create a <td></td> element. We’ll skip over anything fancy here, and just put the post’s subject here.

    Type post.subject and select it. Now press ? > to wrap the selected text inside <%= post.subject %>.

    The resulting index.html.erb is:

    <table>
    ? <tbody>
    ??? <%- @posts.each do |post| -%>
    ????? <tr>
    ??????? <td><%= post.subject %></td>
    ????? </tr>
    ??? <% end -%>
    ? </tbody>
    </table>
    Forms

    Place the cursor inside the new method, and use the ‘Go To’ hot key (? ? ? ↓) and select ‘View’. Press ? to accept new.html.erb.

    Inside the blank new.html.erb file, type ffe and press ?, and type post and press ? twice:

    <%= error_messages_for :post %>
    <% form_for @post do |f| -%>

    <% end -%>
    form_for is the Rails 2.0 preferred helper for managing forms, and there are now snippets for common form_for helpers. There are ff and ffe snippets; the former does not have the error messages section.
    To create a label and text field for the subject attribute:

    Create a <p></p> block (Press ? <, then ?, then ?). Type f. and ?, and select “Label”. Type subject, press ? and press ?. Create a <br /> (? ?). Type f. and ?, and select “Text Field”. Type subject.

    This gives us:

    <%= error_messages_for :post %>
    <% form_for @post do |f| -%>
    ? <p>
    ??? <%= f.label :subject %><br />
    ??? <%= f.text_field :subject %>
    ? </p>
    <% end -%>
    Now repeat for body and published fields.

    Note, for published, you might change the label to Published yet? by tabbing into the default string file.

    Finally, add a “Submit” button using the f. snippet tab completion.

    Start script/server from the prompt and you can now view this form at [url]http://localhost:3000/posts/new[/url]

    The final form is:

    <%= error_messages_for :post %>
    <% form_for @post do |f| -%>
    ? <p>
    ??? <%= f.label :subject %><br />
    ??? <%= f.text_field :subject %>
    ? </p>
    ? <p>
    ??? <%= f.label :body %><br />
    ??? <%= f.text_area :body %>
    ? </p>
    ? <p>
    ??? <%= f.label :published, "Published yet?" %><br />
    ??? <%= f.check_box :published %>
    ? </p>
    ? <p>
    ??? <%= f.submit "Submit" %>
    ? </p>
    <% end -%>
    Note: if you got <br> when hitting ? ? instead of <br /> then you might want to go to the preferences of TextMate (? ,), choose tab “Advanced”, choose “Shell Variables”, click the + sign to add a new shell variable, and give it the name TM_XHTML and a value of? /

    Partials

    The form we just created is exactly the same as the form required for the edit.html.erb template.

    Instead of copy+pasting it into the edit.html.erb file, we’ll create a partial template.

    Select the entire form (? A), and press ? ? H and a dialog box appears. Type in form and press ?.

    You’ll notice a new file _form.html.erb has appeared which contains the code you had selected, while the code in the file new.html.erb has been replaced by:

    <%= render :partial => 'form' %>
    Now copy and paste this into the edit.html.erb file. To create this file, return to the controller (from the new.html.erb file, press ? ? ↓), go to the edit action, and use ? ? ↓ again to create the edit.html.erb template file.

    Link helpers

    At the bottom of the new.html.erb we want a link back to the list of all posts (within the posts controller, not the public blog controller). This will be the index action, and will be accessible via the resources route posts_path.
    There are several link_to snippets that support the resources routes:

    lip – <%= link_to "link text...", model_path(@model) %>
    lipp – <%= link_to "link text...", models_path %>
    linp – <%= link_to "link text...", parent_child_path(@parent, @child) %>
    linpp – <%= link_to "link text...", parent_child_path(@parent) %>
    lim – <%= link_to model.name, model_path(model) %>
    The tab stop points are in useful places.

    So, to create our link to the posts page, type lipp and ?, type Show all posts, press ? twice and type post.
    Controllers: respond_to and redirect_to

    Now we’ll add a create action to the posts_controller.rb. Let’s go there (? ? ↓).

    Below the edit method type def and ?, and type create and ?. Now fill out the create action like:
    def create
    ? @post = Post.new(params[:post])
    ? if @post.save

    ? else

    ? end
    end
    Place the cursor in the true section of the if statement. Type repp and ? to create a redirect_to expression. Press ? again and replace the selected text with post.

    Like the various link_to snippets, there are matching redirect_to snippets.

    rep – redirect_to(model_path(@model))
    repp – redirect_to(models_path)
    renp – redirect_to(parent_child_path(@parent, @child))
    renpp – redirect_to(parent_child_path(@parent))
    There are tab stops in useful places.

    In the false section of the if expression, we’ll demonstrate the respond_to block. There are two ways to generate a respond_to block.
    Type rest and ?, and you get a standard empty block you can work with:

    respond_to do |wants|
    ? wants.html {? }
    end
    Press ? twice to get inside the wants.html block, type ra, press ?, then type new. The final block is:

    respond_to do |wants|
    ? wants.html { render :action => "new" }
    end
    Alternately, there is the “upgrade” hot key (? ? H), where you can convert some existing selected code, into a respond_to block.

    Select the whole line containing the redirect_to expression from the true section of the if statement (? ? L).
    Press ? ? H and the line is replaced with:

    respond_to do |wants|
    ? wants.html do
    ??? redirect_to(posts_path)
    ? end
    ? wants.js {? }
    end
    The js is the first tab stop. The point of this hot key is to instantly refactor your existing html respond code, and support a second response format.

    For now remove the line with wants.js (? ? K).

    The completed create action is:

    def create
    ? @post = Post.new(params[:post])
    ? if @post.save
    ??? respond_to do |wants|
    ????? wants.html do
    ??????? redirect_to(posts_path)
    ????? end
    ??? end
    ? else
    ??? respond_to do |wants|
    ????? wants.html { render :action => "new" }
    ??? end
    ? end
    end
    Yes you’d probably only have one respond_to block, but this is a demo so I am taking the scenic route.

    Our application so far

    In the browser, we can create posts via [url]http://localhost:3000/posts/new[/url] and then view them as a blog visitor at [url]http://localhost:3000/blog.[/url]

    Some more migrations

    We’re looking for the following additions:

    rename the column name of table comments to author
    add a new column author_url to table comments
    add an index to the column post_id of the comments table
    Let’s try to do this all in one migrations file. Start Quick Migration (? ? M). Let’s name it ModifyComments. A new migrations file 003_modify_comments.rb is created and opened, and the cursor is placed behind the mtab trigger. For now delete mtab and instead enter mcol and press ?. Choose Rename / Rename Column (3). Type comments ? name ? author ? ?.

    Again type mcol and ?. This time choose Add / Remove Column (1). Type comments ? author_url, then ? twice, and press ?.

    Now type mind and ?. Choose Add / Remove Index (1). Type comments ? post_id.

    The end result looks like this:

    class ModifyComments < ActiveRecord::Migration
    ? def self.up
    ??? rename_column :comments, :name, :author
    ??? add_column :comments, :author_url, :string
    ??? add_index :comments, :post_id
    ? end

    ? def self.down
    ??? remove_index :comments, :post_id
    ??? remove_column :comments, :author_url
    ??? rename_column :comments, :author, :name
    ? end
    end
    Notice how the down method calls are in reversed order of the up method calls.

    Save the file (? S) and migrate to current (? |).

    Be sure to modify the comments fixture file. Go there (? T, press cy, choose comments.yml). Rename name to author and add a row for author_url for each comment. Check your tests again (? \, choose option 1). All tests should pass.

    Futhermore we’d like to know when a post was published. To do this we’ll want the following modifications:

    keep track of the datetime when a post was published.
    remove the column published from the posts table because it can be determined if a post is published by looking at whether or not a value is present for the published date.
    Start Quick Migration (? ? M). Let’s name it AddPublishedAtForPosts. A new migrations file 004_add_published_at_for_posts.rb is created and opened, and the cursor is placed behind the mtab trigger. Again delete mtab and instead enter mcol and press ?. Choose Add / Remove Column (1). Type posts ? published_at ? datetime ? and ?.

    Again type mcol and ?. Choose Remove / Add Column (5). Type posts ? published and press ? twice.

    The end result looks like this:

    class AddPublishedAtForPosts < ActiveRecord::Migration
    ? def self.up
    ??? add_column :posts, :published_at, :datetime
    ??? remove_column :posts, :published
    ? end

    ? def self.down
    ??? add_column :posts, :published, :boolean
    ??? remove_column :posts, :published_at
    ? end
    end
    Notice how the Remove / Add Column command automagically determined in the down method the column type of column published to be a boolean. It determines this by looking at the current state of your db/schema.rb file.

    Save the file (? S) and migrate to current (? |).

    Now we need to modify the posts fixtures file. Go there (? T, type pyml, choose posts.yml). Replace the line published: true by published_at: 2008-1-1.

    Modify the posts functional test, first go there (? ? ? ↓, choose “Go to Functional Test”). Replace :published => '1' by :published_at => Date.new(2008, 1, 1).

    Modify the post model, first go there (? ? ? ↓, choose “Go to Model”). Have the code look like:

    class Post < ActiveRecord::Base
    ? has_many :comments

    ? def published
    ??? !self.published_at.nil?
    ? end

    ? def published=(publish)
    ??? if publish
    ????? self.published_at = DateTime.now if self.published_at.nil?
    ??? else
    ????? self.published_at = nil
    ??? end
    ? end
    end
    Modify the blog_controller.rb file. Replace Post.find_all_by_published(true) by Post.find(:all, :conditions => "published_at IS NOT NULL").

    Finally, check your tests again (? \). All tests should pass.



    本文轉(zhuǎn)自 fsjoy1983 51CTO博客,原文鏈接:http://blog.51cto.com/fsjoy/73182,如需轉(zhuǎn)載請自行聯(lián)系原作者

    總結(jié)

    以上是生活随笔為你收集整理的textmate开发一个blog的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 国产欧美亚洲精品 | 国产精品一区二三区 | 麻豆影视在线免费观看 | 成人亚洲一区二区 | av成人亚洲 | 亚洲欧美一区二区视频 | 久草精品视频在线观看 | 欧美亚洲网站 | www.污视频 | 欧美亚洲在线视频 | 日韩视频h| 欧美xo影院 | 欧美极品第一页 | 一区二区激情 | 久久久久久久一区 | 凹凸日日摸日日碰夜夜 | 中文字幕亚洲乱码熟女一区二区 | 欧美性免费 | 日本中文字幕在线看 | 国产一区不卡在线观看 | 国产日韩欧美二区 | 扒下小娇妻的内裤打屁股 | 午夜电影一区二区 | 国产一区二区三区四区hd | 在线免费观看中文字幕 | 国内精品久久久久久久久久 | 亚洲免费av网址 | 九九九九九九精品 | 久久伊人亚洲 | av网站在线免费看 | 国产成人精品一区二区三区无码熬 | 亚洲一区二区三区激情 | 国产精品刺激 | eeuss一区二区 | 日韩av中文字幕在线免费观看 | 中文字幕观看 | 国产99久一区二区三区a片 | 成人国产在线视频 | 欧美一区二区免费视频 | 福利网站在线 | 日日噜噜噜夜夜爽爽狠狠 | 最新毛片网 | 国产又粗又硬又黄的视频 | 国产精品日韩一区二区 | 国产成人免费av | 日本一级片在线播放 | 国产一级淫片a视频免费观看 | 茄子香蕉视频 | 91成人在线免费 | 日韩欧美日韩 | 黄网站色视频免费观看 | 久久久久久久亚洲av无码 | 国产91免费视频 | 日韩激情在线播放 | 琪琪色在线观看 | 一区二区三区天堂 | 国产r级在线 | 国产一级伦理片 | 亚洲精品乱码久久久久久国产主播 | 极品国产在线 | 超碰国产在线观看 | 国产性猛交普通话对白 | 曰韩毛片 | 国产美女激情视频 | 鲁一鲁在线视频 | 女生毛片 | 婷婷看片 | eeuss国产一区二区三区黑人 | 国产超碰 | 强乱中文字幕av一区乱码 | 99久久精品久久久久久清纯 | 中文字幕日韩精品亚洲一区小树林 | 日韩在线视频网址 | 99精品国产免费 | 亚洲区 欧美区 | 精品日韩在线播放 | 成人依人 | 大尺度做爰呻吟舌吻网站 | 亚洲性天堂 | 中文字幕在线网 | 欧美视频成人 | 日本狠狠爱 | 午夜激情视频在线播放 | 15—16女人毛片 | 日本一道本 | 无码乱人伦一区二区亚洲 | 波多野结衣一区二区三区免费视频 | 久久久久久国产精品三区 | 精品视频99 | 亚洲wwww| 在线色播 | 老熟妇一区二区三区啪啪 | 欧美激情一级精品国产 | 一级大黄色片 | 成人学院中文字幕 | 欧美人与禽zoz0性3d | 美女mm131爽爽爽免费动视频 | 久久精品国产免费看久久精品 | 91精品久久久久久久久久入口 |