Sinatra+SQLite3+DataMapper - 十分完整的tutorial - “Superdo”

weixin_34279184發表於2014-03-17

原文地址:https://ididitmyway.herokuapp.com/past/2010/3/30/superdo_a_sinatra_and_datamapper_to_do_list/

這個tutorial說明:怎麼構建一個list app,其中要用到資料庫來儲存task。

tutorial概括以下技術:

  • 安裝 SQLite and Datamapper
  • 連線資料庫
  • 資料庫中的CRUD 動作
  • REST風格的urls

我在這裡主要做的是根據我的實際操作和理解,把整個過程用我熟悉的中國話記錄下來,以便下次我還能根據它實現或修改這個App,僅此而已。

開始tutorial前,確保已經安裝了Sinatra、Ruby和Ruby Gems。

安裝 SQLite and Datamapper

這裡使用SQLite作為資料庫;使用Datamapper作為ORM連線資料庫。

如果你在用Ubuntu/Debian系統,這樣安裝SQLite

sudo aptitude install sqlite3
gem install sqlite3-ruby --  --with-sqlite3-dir=/usr/local/lib

 

這樣安裝DataMapper GEM

sudo gem install data_mapper

 還有一個adapter,連線DataMapper到資料庫用的

sudo gem install dm-sqlite-adapter

Note:原文還有Heroku的相關設定,我省略了。

 

連線到資料庫(可能包括:產生、連線、插入、查詢、刪除等等)

在專案根目錄建立main.rb檔案,它之後就是此App的主檔案。內容如下:

require 'rubygems'
require 'sinatra'
require 'data_mapper'

DataMapper.setup(:default,ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/development.db")

#定義資料類(model class)
class Task
	include DataMapper::Resource #用include方式包含DM的功能,而沒有使用繼承
	property :id,Serial
	property :name,String
	property :completed_at,DateTime
end


DataMapper.auto_upgrade!

bit by bit:點點滴滴

程式碼說明:

1. first bit(第一部分)

require 'rubygems'
require 'sinatra'
require 'data_mapper'

  請求必要的gems。

2. next bit

DataMapper.setup(:default, ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/development.db")

它是資料庫連線字串。ENV['DATABASE_URL'] || "sqlite3://#{Dir.pwd}/development.db" 在使用Heroku是首選連線到線上資料庫,如果沒有才會連線本地的development.db。

而且,如果你還沒有產生development.db,執行以上程式碼會自動產生資料庫檔案。

3. Next part 是Task Class定義。

值得注意的是第一行定義的:id,它是unique的,且由於型別是Srial導致其auto-increment

:completed_at,DateTime這一行告訴我們:Any task with a value of nil, will not have been completed.(沒設定completed的Task,其completed_at=nil)

4.Last part of code

讓DataMapper更新資料庫,將Task的改變提交上去。this means(通過這種方式)甚至可以把增加/刪除屬性(Task類的)反映到資料庫中。

如果想wipe away(擦去)所有資料(?),可以用DataMapper::auto_migrate!,但是使用要小心!!!

 

資料庫準備好了,現在可以不用web介面,在終端狀態下瀏覽(巡視)一下你的資料庫

在終端輸入:

irb -r ./main.rb

說明:這會開啟一個irb shell,-r 引數使得.rb 檔案中的程式碼被包含在這個shell中。在這裡,你已經連線好了資料庫,現在試試[新建][編輯][查詢][刪除]Task吧!

下面的操作都是Task Class最常用的,我直接引用原文啦

進入irb shell :

>$ irb -r main.rb

First Task.all , 檢視 all our tasks:

$irb(main): > Task.all
=> [] #返回[]表示還沒有

so let’s create one:

$irb(main): > t = Task.new
=> #<Task @id=nil @name=nil @completed_at=nil>

$irb(main): > t.name = "Get milk"
=> "Get milk"

Task.new 物件在記憶體中 in memory - 還要手工存入資料庫 :

irb(main):007:0> t.save
=> true

檢視一下:

irb(main):008:0> Task.first
=> #<Task @id=1 @name="Get milk" @completed_at=nil>

什麼時候都可以用Task.create()建立,顯然這是類方法:

irb(main):009:0> Task.create(:name => "Get bananas")
=> #<Task @id=2 @name="Get bananas" @completed_at=nil>

Notice用這種方式建立的,不需要手工save,它已經存入資料庫了。

irb(main):010:0> Task.all
=> [#<Task @id=1 @name="Get milk" @completed_at=nil>, #<Task @id=2 @name="Get bananas" @completed_at=nil>]

Task.all返回一個集合collection,因此它的count method返回內容的數量:

irb(main):011:0> Task.all.count
=> 2

This shows us that there are currently two tasks saved in the database.

That has covered creating and reading records in our database. Now let’s have a look at updating. Let’s say that we want to get half fat milk. First we need to find that record.

irb(main):012:0> t = Task.first(:name => "Get milk") #這樣會返回第一個名字是“Get milk“的記錄
=> #<Task @id=1 @name="Get milk" @completed_at=nil>

This is an example of how to find records in the database using certain parameters. In this case we wanted the task with the name “Get milk”. This is now stored in the variable t.

更新記錄有兩種辦法:

The first way 手工修改 && save 儲存,

irb(main):014:0> t.name = "Get half fat milk"
=> "Get half fat milk"
irb(main):015:0> t.save
=> true
irb(main):016:0> t
=> #<Task @id=1 @name="Get half fat milk" @completed_at=nil>

The second way 呼叫 update method. (它會自動將修改儲存到資料庫)

 irb(main):017:0> t.update(:name => "Get full fat milk")
 => true
 irb(main):019:0> t
 => #<Task @id=1 @name="Get full fat milk" @completed_at=nil>

這些都是 CRUD 操作(actions)

我們還差最後一個 Deleting 操作 (using the destroy method ):

irb(main):020:0> t = Task.get(1)
=> #<Task @id=1 @name="Get full fat milk" @completed_at=nil>
irb(main):022:0> t.destroy
=> true

Notice 呼叫 get method 找到的是id=1的task。This can only be used if you use the primary key to search for it. In this case the primary key is the id, which is 1 for this task.

We will be using this quite often later to get the tasks from unique urls. We can check that it has been deleted by asking to see all the tasks again:

irb(main):023:0> Task.all
=> [#<Task @id=2 @name="Get bananas" @completed_at=nil>]

Now we can see that only our second task to “Get bananas” is still saved in the database.

 

RESTful urls and CRUD Actions(URL router部分)

The web interface that we will create to interact with our database will be based on the REST principle.
根據REST原則建立的web ui 將會影響前面的db。

這裡會使用http verb(動詞):POST、GET、PUT、DELETE;db方面則有對應的CRUD actions。

View a task

對於每個task,最基礎的URL可能是這樣的:/task/:id(id是task的主鍵)。無論是read/update/delete都需要瀏覽器傳遞http verb。

下面建立一個handler of Views task,開啟main.rb,增加程式碼:

require 'rubygems'
require 'sinatra'
require 'data_mapper'

DataMapper.setup(:default,"sqlite3://#{Dir.pwd}/development.db")

#定義資料類(model class)
class Task
    include DataMapper::Resource #用include方式包含DM的功能,而沒有使用繼承
    property :id,Serial
    property :name,String
    property :completed_at,DateTime
end

#View a task
get '/task/:id' do
    @task=Task.get(params[:id])
    erb :task
end

DataMapper.auto_upgrade! # this must at last line

程式碼說明:對於新增部分(灰色背景的程式碼),{@task=Task.get(params[:id])}通過URL(/task/:id)其中的id會得到一個task,並放在物件欄位@task中。

erb :task 讓sinatra顯示一個task view(使用erb模板),現在還沒有這個模板,所以下面建立此模板檔案(./views/task.erb),模板檔案應該放在views目錄(這是預設配置決定的),內容: 
<h2><%= @task.name%></h2>

task.erb模板只能顯示task name內容,如果有一個網站框架的模板就太帥了,現在建立一個名叫layout.erb的模板檔案:

<!DOCTYPE html>
<html>
    <head>
        <title>To Do List</title>
        <meta charset="utf-8"/>
    </head>

    <body>
        <h1>To Do List</h1>
        <%= yield%><!-- task.erb etc. files entried into here-->
    </body>
</html>

呼~~,現在可以看看你上面都幹了什麼了,在終端啟動主檔案吧

ruby main.rb

待啟動後,瀏覽器導航地址http://localhost:4567/task/2,看看有啥!呵呵

Create a new Tasks(using a form)

Create action一般都分成兩個handler來處理:

  • 一個顯示(輸入)表單,名叫“new";
  • 另一個處理建立task動作。

首先從顯示窗體的new handler開始,使用者用URL(/task/new)就能顯示窗體

這裡注意:新程式碼要放在view handler前面。

#new handler - display input form
get '/task/new' do
    erb :new
end

new views的模板new.erb

<form action="/task/create" method="post">
    <input type="text" name="name" id="name">
    <input type="submit" value="Add TAsk!"/>
</form>

 

 

 

 

 

 

 

相關文章