基本 CRUD 程式


以下將利用先前的文件中談到的內容作基礎,快速建立一個線上書籤程式,可進行基本的CRUD操作。

首先建立應用程式專案資料夾:

~\$ rails new bookmark

接著進入bookmark資料夾,Liunx的使用者,可能必在Gemfile中加入以下內容,再執行一次bundle intall,後續的操作才能進行:

  • Gemfile
gem 'therubyracer'

執行db:create任務:

~/hello\$ bundle exec rake db:create

建立Model(本來想取bookmark,不過Rails說自己有用到bookmark這個名稱,所以只好使用page這個名稱了XD):

~/hello\$ rails g model page title:string url:text description:text

執行db:migrate任務:

~/hello\$ bundle exec rake db:migrate

建立Controller:

~/hello\$ rails g controller bookmarks index new create show edit update destroy

這會在app/controllers中產生bookmarks_controller.rb,當中建立了index、new、create、show、edit、update、destroy等空的方法,並在app/views/bookmarks中建立index.html.erb、new.html.erb、create.html.erb、edit.html.erb、update.html.erb、destroy.html.erb等檔案,而對config/routes.rb也會增加以下的設定:
  • routes.rb
get "bookmarks/index"
get "bookmarks/new"
get "bookmarks/create"
get "bookmarks/show"
get "bookmarks/edit"
get "bookmarks/update"
get "bookmarks/destroy"

然而這邊不使用這些設定,請將之刪除,自行加入:
  • routes.rb
root :to => 'bookmarks#index'
match ':controller(/:action(/:id(.:format)))'

接下來刪除public/index.html,並編輯bookmarks_controller.rb中的index方法:
  • bookmarks_controller.rb
def index
    @pages = Page.all
end

首頁會取得所有的書籤頁面資料,取得的物件擁有each方法,接下來要在index.html.erb後定義畫面:
  • index.html.erb
<ul>
  <% @pages.each do |page| %>
    <li>
      <%= link_to page.title, page.url %>
      <%= link_to "Details", :controller => 'bookmarks', :action => 'show', :id => page %>
      <%= link_to "Edit", :controller => 'bookmarks', :action => 'edit', :id => page %>
      <%= link_to "Delete", :controller => 'bookmarks', :action => 'destroy', :id => page %>
    </li>
  <% end %>
</ul>
<%= link_to "New", :controller => 'bookmarks', :action => 'new' %>

<%與%>之間可撰寫Ruby程式碼,上面的設定中,當你嘗試直接顯示page,會傳回id值。

接下編輯bookmarks_controller.rb中的new方法:
  • bookmarks_controller.rb
def new
    @page = Page.new
@page.url = "http://"
end

這建立了一個Page物件,可以在new.html.erb中進行表單填寫:
  • new.html.erb
<%= form_for @page, :url => { :controller => 'bookmarks', :action => 'create' } do |f| %>
    <%= f.label :title, "Title:" %><%= f.text_field :title %><br>
    <%= f.label :url, "Url:" %><%= f.text_field :url %><br>
    <%= f.label :description, "Description:" %><br>
    <%= f.text_area :description %><br>
    <%= f.submit "Create" %>
<% end %>

form_for輔助方法會產生<form>表單,預設是POST,區塊參數f是代表該表單的實例,f.label方法產生<label>,第一個參數用來設定for屬性,第二個參數用來作為顯示名稱;f.text_field用來產生type為text的<input>,第一個參數用來產生id屬性與請求參數名稱的參考;f.text_area用來產生<textarea>,第一個參數用來產生id屬性與請求參數名稱的參考;f.submit用來產生type為submit的<input>,第一個參數用來作為顯示名稱。

一個傳回的HTML參考如下所示:
<!DOCTYPE html>
<html>
<head>
  <title>Bookmark</title>
  <link href="/assets/application.css?body=1" media="screen" rel="stylesheet" type="text/css" />
<link href="/assets/bookmarks.css?body=1" media="screen" rel="stylesheet" type="text/css" />
  <script src="/assets/jquery.js?body=1" type="text/javascript"></script>
<script src="/assets/jquery_ujs.js?body=1" type="text/javascript"></script>
<script src="/assets/bookmarks.js?body=1" type="text/javascript"></script>
<script src="/assets/application.js?body=1" type="text/javascript"></script>

  <meta content="authenticity_token" name="csrf-param" />
<meta content="F8SdRtXBB/7fNZYSIrWVKvFjiNtJ6LndWAOXPHB0zE4=" name="csrf-token" />
</head>
<body>

<form accept-charset="UTF-8" action="/bookmarks/create" 
class="new_page" id="new_page" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="&#x2713;" />
<input name="authenticity_token" type="hidden"
 value="F8SdRtXBB/7fNZYSIrWVKvFjiNtJ6LndWAOXPHB0zE4=" />
</div> <label for="page_title">Title:</label>
<input id="page_title" name="page[title]" size="30" type="text" /><br> <label for="page_url">Url:</label>
<input id="page_url" name="page[url]" size="30" type="text" /><br> <label for="page_description">Description:</label><br> <textarea cols="40" id="page_description" name="page[description]" rows="20"></textarea><br> <input name="commit" type="submit" value="Create" /> </form>
</body> </html>

表單會送出bookmarks/create,編輯bookmarks_controller.rb如下:
  • bookmarks_controller.rb
def create
    @page = Page.new(params[:page]) # 根據表單內容,直接建立Page實例
@page.save
end

(Rails 的許多範例,常見以上把params回傳的物件整個直接填入某物件的例子,方便是方便,但必須考慮安全上的問題,例如在模型中,預設所有欄位都可存取,必須考慮對屬性使用attr_protected或attr_accessible加以防護。)

儲存後在create.html.erb顯示成功訊息與回到首頁鏈結:
  • create.html.erb
<h1>Success</h1>
<%= link_to "Home", root_path %>

接著來撰寫取得書籤細節的show方法:
  • bookmarks_controller.rb
def show
    @page = Page.find(params[:id])
end

接著是顯示書籤細節的頁面:

  • show.html.erb
<h1><%= @page.title %></h1>
<h2><%= @page.url %></h2>
<%= simple_format(@page.description) %><br>
<%= link_to "Home", root_path %> 
<%= link_to "Edit", :controller => 'bookmarks', :action => 'edit', :id => @page %>
<%= link_to "Delete", :controller => 'bookmarks', :action => 'destroy', :id => @page %>

simple_format是個輔助方法,會自動將'\n'置換為<br>。在顯示細節的頁面中有個編輯按鈕,按下後可以對既有書籤進行修改,要修改書籤,基本上就是先取得書籤:

  • bookmarks_controller.rb
def edit
    show
end

因為要取得書籤,在這邊直接呼叫了先前定義過的show方法,接著是顯示編輯書籤表單,這跟新增書籤的表單很像,只不過控制器的動作是update,而f.submit的字樣改為
"Update"

  • edit.html.erb
<%= form_for @page, :url => { :controller => 'bookmarks', :action => 'update', :id => @page } do |f| %>
    <%= f.label :title, "Title:" %><%= f.text_field :title %><br>
    <%= f.label :url, "Url:" %><%= f.text_field :url %><br>
    <%= f.label :description, "Description:" %><br>
    <%= f.text_area :description %><br>
    <%= f.submit "Update" %>
<% end %>

接著是發送更新表單時處理的update方法:

  • bookmarks_controller.rb
def update
    show
@page.update_attributes(params[:page])
end

以及顯示更新成功的頁面:
  • update.html.erb
<h1>Success</h1>
<%= link_to "Home", root_path %>

最後是處理刪除書籤的destroy方法:
  • bookmarks_controller.rb
def destroy
    show
@page.destroy
redirect_to :action => :index
end

刪除書籤後,可使用redirect_to輔助方法,直接要求瀏覽器回到首頁,看到書籤少了一筆,就知道刪除成功了,因此先前自動產生的destroy.html.erb可以刪除不用。

完成以上之後,在專案資料夾中輸入rails s,使用瀏覽器連接http://localhost:3000,就可以開始使用應用程式了。