"15分鐘搭建一個(gè)博客系統(tǒng)"剖效,是Ruby On Rails非常經(jīng)典Demo練習(xí)。rails的創(chuàng)始人DHH當(dāng)年用一個(gè)視頻演示了如何在15分鐘內(nèi)搭建一個(gè)博客系統(tǒng)焰盗,展示除了rails的優(yōu)雅與靈活璧尸,也讓更多的人開始關(guān)注rails。
之所以能在15分鐘內(nèi)搭建一個(gè)博客系統(tǒng)熬拒,是與rails的一個(gè)原則:“慣例優(yōu)于設(shè)置“(Convention Over Configuration)分不開的爷光。而在搭建過程中,最重要的是使用到了rails中的scaffold(腳手架)功能澎粟。
下面蛀序,我們來(lái)演示如何實(shí)現(xiàn)15分鐘搭建一個(gè)博客系統(tǒng)欢瞪。
系統(tǒng)環(huán)境版本
ubuntu-1404
ruby-2.3.0
rails-5.0.0.1
博客實(shí)現(xiàn)功能
- 可以新建、讀取徐裸、更新遣鼓、刪除blog
- 提供blog的評(píng)論功能,每個(gè)blog下可以有多條評(píng)論
系統(tǒng)設(shè)計(jì)流程演示
(一)實(shí)現(xiàn)blog的新建重贺、讀取荷并、更新硼砰、刪除功能
- 新建工程
$ rails new blog_of_vito
- 打開工程拐叉,新建scaffold(腳手架)
$ rails g scaffold article
我們看到命令行中顯示:
invoke active_record
create db/migrate/20161129044734_create_articles.rb
create app/models/article.rb
invoke test_unit
create test/models/article_test.rb
create test/fixtures/articles.yml
invoke resource_route
route resources :articles
invoke scaffold_controller
create app/controllers/articles_controller.rb
invoke erb
create app/views/articles
create app/views/articles/index.html.erb
create app/views/articles/edit.html.erb
create app/views/articles/show.html.erb
create app/views/articles/new.html.erb
create app/views/articles/_form.html.erb
invoke test_unit
create test/controllers/articles_controller_test.rb
invoke helper
create app/helpers/articles_helper.rb
invoke test_unit
invoke jbuilder
create app/views/articles/index.json.jbuilder
create app/views/articles/show.json.jbuilder
create app/views/articles/_article.json.jbuilder
invoke assets
invoke coffee
create app/assets/javascripts/articles.coffee
invoke scss
create app/assets/stylesheets/articles.scss
invoke scss
create app/assets/stylesheets/scaffolds.scss
短短一行代碼计福,便為我們創(chuàng)建了這么多的功能淤年,其中包括model層(M)吼句、view層(V)和controller層(C)柳恐,以及遷移(migration)胎撇、路由(routing)贫贝、helper方法秉犹、測(cè)試功能等其他一些方法。而在按照這種約定生成的文件中稚晚,我們可以發(fā)現(xiàn)已經(jīng)自動(dòng)生成了很多代碼崇堵,我們只需要添加部分具體實(shí)現(xiàn)功能的代碼即可完成整個(gè)系統(tǒng)。換句話說客燕,通過rails的約定鸳劳,scaffold為我們提供了一個(gè)框架,通過填增加一些必要的代碼也搓,我們便可以輕松地實(shí)現(xiàn)我們需要的功能赏廓。真的是很方便吶!
- 為blog添加字段
blog需要有題目和內(nèi)容傍妒,我們需要在Article模型對(duì)應(yīng)的表上添加這兩個(gè)字段幔摸。
我們打開/db/migrate/*_create_articles.rb
文件,修改為:
def change
create_table :articles do |t|
t.string :title
t.text :text
t.timestamps
end
end
運(yùn)行遷移:
$ rails db:migrate
如果rails版本低于5.0颤练,執(zhí)行命令:
$ rake db:migrate
看到打印信息:
== 20161129044734 CreateArticles: migrating ===================================
-- create_table(:articles)
-> 0.0012s
== 20161129044734 CreateArticles: migrated (0.0012s) ==========================
說明字段已經(jīng)添加到表中了既忆。
- 修改
articles_controller.rb
文件
打開文件,我們發(fā)現(xiàn)scaffold已經(jīng)為我們生成了index
嗦玖、show
患雇、new
、edit
宇挫、create
庆亡、update
、destroy
方法捞稿,還生成了兩個(gè)私有方法:set_article
又谋、article_params
拼缝。這些方法基本實(shí)現(xiàn)了整個(gè)blog的新建、讀取彰亥、更新咧七、刪除的功能。我們只需要告訴controller我們需要使用的字段即可任斋。
修改article_params
方法為:
def article_params
params.require(:article).permit(:title, :text)
end
- 修改view文件
1.修改/app/view/articles/_form.html.erb
文件為:
<%= form_for @article do |f| %>
<% if @article.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@article.errors.count, "error") %> prohibited this article from being saved:</h2>
<ul>
<% @article.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br>
<%= f.text_area :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
在這個(gè)文件中继阻,我們將前幾行中的article
換成@article
,同時(shí)添加了blog填寫及提交title和text的表單內(nèi)容废酷。
_form.html.erb
是一個(gè)局部視圖瘟檩,按照約定,局部視圖的文件名以下劃線開頭澈蟆。由于在編輯文章頁(yè)面和新建文章頁(yè)面很相似墨辛,顯示表單的代碼是相同的,使用局部視圖可以去掉兩個(gè)視圖中的重復(fù)代碼趴俘,因此我們直接在這個(gè)文件中添加表單即可睹簇,而不用分別在new.html.erb
和edit.html.erb
文件中添加相同的代碼。
之所以能在兩個(gè)動(dòng)作中共用一個(gè) form_for寥闪,是因?yàn)?code>@article是一個(gè)資源太惠,對(duì)應(yīng)于符合 REST 架構(gòu)的路由,Rails 能自動(dòng)分辨使用哪個(gè)地址和請(qǐng)求方法疲憋。
2.修改index.html.erb
文件為:
<p id="notice"><%= notice %></p>
<h1>Articles</h1>
<table>
<thead>
<tr>
<th>Title</th><!--new-->
<th>Text</th><!--new-->
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td><!--new-->
<td><%= article.text %></td> <!--new-->
<td><%= link_to 'Show', article %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Article', new_article_path %>
新加的部分我們使用``標(biāo)示出來(lái)凿渊,用來(lái)實(shí)現(xiàn)顯示文章題目和內(nèi)容的功能。
3.修改show.html.erb
文件為:
<p id="notice"><%= notice %></p>
<p>
<strong>Title:</strong>
<%= @article.title %>
</p>
<p>
<strong>Text:</strong>
<%= @article.text %>
</p>
<%= link_to 'Edit', edit_article_path(@article) %> |
<%= link_to 'Back', articles_path %>
這里添加顯示blog的title和text的功能缚柳。
- 修改
app/models/article.rb
文件
這里修改model文件埃脏,是為了添加一些約束,這里我們要求blog的title不能為空且長(zhǎng)度大于3喂击,當(dāng)不滿足要求時(shí)頁(yè)面會(huì)報(bào)錯(cuò)剂癌。
修改article.rb
為;
class Article < ApplicationRecord
validates :title, presence: true,
length: { minimum: 3 }
end
這樣我們成功建立了一個(gè)可以新建翰绊、讀取查詢佩谷、更新和刪除文章的blog系統(tǒng),是不是很簡(jiǎn)單凹嗍取谐檀!
- 系統(tǒng)首頁(yè)效果圖:
這樣,我們的第一部分功能就算是實(shí)現(xiàn)了裁奇。
(二)添加blog評(píng)論功能
這部分我們需要添加blog的評(píng)論功能桐猬。我們知道對(duì)一篇博客評(píng)論時(shí)我們只需要在對(duì)應(yīng)的博客顯示頁(yè)面下進(jìn)行評(píng)論即可,因此對(duì)于評(píng)論來(lái)說刽肠,只需要MC層溃肪,而其V層則在/app/views/articles/show.html.erb
中實(shí)現(xiàn)即可免胃。
因此,我們?cè)谶@里不使用scaffold來(lái)建立評(píng)論惫撰。
- 新建評(píng)論model層:
$ rails g model comment article_id:integer commenter:string body:text
- 運(yùn)行遷移(rails >= 5.0)
$ rails db:migrate
- 添加評(píng)論與文章的對(duì)應(yīng)關(guān)系
一個(gè)評(píng)論只能對(duì)應(yīng)一篇文章羔沙,一篇文章可以又多條評(píng)論。
修改article.rb
為:
class Article < ApplicationRecord
validates :title, presence: true,
length: { minimum: 3 }
has_many :comments
end
修改comment.rb
為:
class Comment < ApplicationRecord
belongs_to :article
end
- 生成comment控制器
$ rails g controller comments
- 修改
comments.rb
為:
class CommentsController < ApplicationController
def create
@article = Article.find(params[:article_id])
@comment = @article.comments.create(comment_params)
redirect_to article_path(@article)
end
private
def comment_params
params.require(:comment).permit(:commenter, :body)
end
end
- 在
/app/views/articles/show.html.erb
文件中添加:
<h2>Comments</h2>
<% @article.comments.each do |comment| %>
<p>
<strong>Commenter:</strong>
<%= comment.commenter %>
</p>
<p>
<strong>Comment:</strong>
<%= comment.body %>
</p>
<% end %>
<h2>Add a comment:</h2>
<%= form_for([@article, @article.comments.build]) do |f| %>
<p>
<%= f.label :commenter %><br>
<%= f.text_field :commenter %>
</p>
<p>
<%= f.label :body %><br>
<%= f.text_area :body %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
這部分代碼負(fù)責(zé)添加評(píng)論及評(píng)論的顯示功能厨钻。
- 在
routes.rb
中修改路由為:
resources :articles do
resources :comments
end
現(xiàn)在扼雏,我們的blog系統(tǒng)就已經(jīng)搭建完成了。
我們來(lái)看看添加評(píng)論后的效果:
總結(jié)
我們成功的搭建了一個(gè)博客系統(tǒng)夯膀。在搭建過程中诗充,我們看到了scaffold的強(qiáng)大功能,短短一行代碼為我們實(shí)現(xiàn)了很多很多的功能诱建,而這就是rails的魅力蝴蜓。
事實(shí)上,我們完全可以自己來(lái)實(shí)現(xiàn)scaffold的功能涂佃,在文中我們將scaffold中的mvc簡(jiǎn)單地介紹了一下励翼。scaffold為我們提夠了足夠多的功能蜈敢,但并非所有的都是我們需要的辜荠,在遇到實(shí)際問題時(shí),需不需要使用scaffold抓狭,還得根據(jù)實(shí)際需求來(lái)決定伯病。