終於到了這一刻,
這一章開始就要見識到Rails有多Powerful,
我們先前說過Rails是一個框架,如果是處理基本的CRUD,
循著這個框架去做的速度簡直是比一塊小蛋糕還輕鬆。
我並不打算一次就把MVC給介紹完,畢竟從來沒接觸過的看完之後只會有種見樹不見林的錯覺。
所以老實說不太能接受幾乎每本書都這樣編排XD
不如我們直接各個擊破最後再一次彙整吧!
個人相當喜歡令狐沖最後將各家內力混合在一起後神功大成之感,
什麼?吸星大法是邪教武功,非也非也他最後還是學會了易筋經(誤
這裡我們只focus在model上,其他兩個先不要管。
首先我們必須接觸到的是Model,Model是我們跟資料庫互動的媒介,
所有跟資料庫有關的邏輯處理都放在這裡(暫時是這樣,以後再討論有哪個更好的位置可以放邏輯相關的ruby code)
接著就直接打開terminal,在project的資料夾輸入:(別急著按enter)
rails g model post
g = generate
我們其實可以在產生model的時候就順便設定這個post在資料庫屬於他的table中會有哪些columns。
table可以把它想成對應到po文的class,
而每則po文都是符合這個class被產生出來的實例,對應到資料庫裡面的一個列(row)。
這個物件有的屬性會對應到的不同column。
補充:
產生物件並不代表就在資料表裡面生成東西,
這裡rails有activerecord這個orm幫我們做好mapping這件事。
Object Relational Mapping,簡稱ORM。
想是直接想成這樣子,但實際上orm運作的情形應該是讓我們用物件導向的思維來操作資料庫,
並非產生的物件就代表生成資料庫裡的東西,
在執行save method之後orm才會幫我們對應過去,(在rails裡面就是activerecord)
讓我們能夠用物件導向的方式來操作資料庫,不用去手刻SQL。
特別感謝kevin幫忙補充這一點,太快講過去沒注意到會造成誤會,
下方回應有他舉的例子可以看,這裡就不複製貼上了。
關於orm以及activerecord更深入的資料可以參考:
http://ihower.tw/rails3/activerecord.html
http://zh.wikipedia.org/wiki/%E5%AF%B9%E8%B1%A1%E5%85%B3%E7%B3%BB%E6%98%A0%E5%B0%84
然後我們可以回頭看一下第四天的文章,我們規劃的po文會有哪些欄位是比較基本可以現在先做的:
標題、內容、附註、資料來源看起來比較簡單應該是可以先做的,
除了內容可能會超過string限制的255字,其他都用string。
所以輸入的變成:
rails g model post title:string content:text note:string source:string
invoke active_record
create db/migrate/20140923035422_create_posts.rb
create app/models/post.rb
invoke test_unit
create test/models/post_test.rb
create test/fixtures/posts.yml
在這裡我們先點進去db/migrate/20140923035422\_create\_posts.rb
這支檔案看一下:
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :content
t.string :note
t.string :source
t.timestamps
end
end
end
這裡我們只要跑budle exec rake db:migrate
,
Activie Record就會自動幫我們新建這個table了,不用自己去操作sql。
直接執行rake db:migrate也是可以的,只是bundle exec會執行這個資料夾底下Gemfile版本的gem,
用講的可能看起來有點不懂,其實噴過一次錯就會懂了,
總之這就是個好習慣啦XD
這裡我們還沒有辦法在瀏覽器上看到我們新增的post,
那要怎麼確認table是不是真的有被新建呢?
在project資料夾底下執行rails c --sandbox
c
是console的意思,如果你寫過javascript,這個應該會有點熟悉。
--sandbox
加上這個選項後會進入沙盒模式,當我們離開時做的一切都會被還原,
這裡我們只是要測試一下剛剛新增的資料表有沒有用
如果想要有更好用的console,建議裝pry-rails這個gem,
他會用pry來取代原本內建的irb,pry非常的好用,
重點是......也比較好看。
方法很簡單,只要打開Gemfile加入這一段:
group :development, :test do
gem 'pry-rails'
end
再執行bundle install就可以了,
group裡是指定在哪個環境下裝這個gem,
像這裡就是開發和測試才會用到pry-rails這個gem。
接著就讓我們讓我們直接在console跟資料庫做互動吧!
post = Post.new(title:"標題", content: "測試內容", note:"假備註", source:" sample.com")
#<Post id: nil, title: "標題", content: "測試內容", note: "假備註", source: " sample.com", created_at: nil, updated_at: nil>
這裡我們指定了變數post,他借由Post這個class新增了一列資料,
id, created_at還有updated_at是內建的欄位,他們現在還是nil代表我們還沒將資料存進去,
現在只要執行post.save
就會看到active record幫我們做了哪些事情:(現在看不懂也沒關係,我們需要的只是熟練再熟練)
(0.7ms) SAVEPOINT active_record_1
SQL (4.1ms) INSERT INTO "posts" ("content", "created_at", "note", "source", "title", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["content", "測試內容"], ["created_at", "2014-09-23 05:43:46.016161"], ["note", "假備註"], ["source", " sample.com"], ["title", "標題"], ["updated_at", "2014-09-23 05:43:46.016161"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
雖然前端測試真正讓使用者輸入的地方也很重要,
但大部分debug的時候,還是離不開console的,
在這裏先對model和active record有一定的理解會讓接下來的步驟不那麼寸步難行,
Rails的學習曲線說陡峭其實也還好,只是太多事情太簡單太magic,常常還沒搞清楚發生什麼事情一切就做完了XD
而方便帶來的代價就是當真的出什麼事情,永遠都是滿頭的wtf,
明天的主題則是像前一天的controller一樣給post自己的頁面和路徑,
不一樣的是這次我們要從資料庫把資料拿出來了,
有朋友跟我反應這樣寫的囉哩八嗦的,但這都是為了未來做準備,
一步步理解才不會哪一天突然被magic反噬了!
另外也是想將各個不同的單元做比較細的切割,
一天想要講太多主題是不切實際的事情,
明天見!
table可以把它想成是po文的class,
而每則po文都是符合這個class被產生出來的實例,儲存在資料庫裡面會變成一列。
每一列的不同column就代表這個物件有的屬性。
這一段敘述蠻奇怪的。
ORM 是讓你使用物件導向的思維來操作資料庫的工具,而 table,column 是關聯性資料庫裡面的東西,一個資料庫由一或多個 table 組成,一個 table 裡面有一或多個 column,而一個 table 裡面也可能有一或多筆 record。
假設我們在 controller 裡面這樣寫:
@post = Post.new
實際上它是產生一個 Ruby Object 。
假設我們 call save method :
@post.save
ORM 會幫我們跟資料庫連接,執行儲存這筆資料的動作。
假設 post 這個 table 有 title, content 這兩個 column ,今天我們想要儲存一筆新資料的話會這樣寫:
@post = Post.new
@post.title = "test name"
@post.content = "hi"
但要記住的是,直到我們執行 save method 之前,這些動作實際上都只是更改 RUby Object 的值而已。
table, column 跟 class 以及 Object 的 attriubte,是無法畫上等號的。兩個完全是不一樣的東西。
ORM 只是把原本開發者需要自己手寫 SQL 的部分抽象化,讓我們直接使用物件導向程式語言操作資料庫,我們不需要管跟資料庫連接或是要怎麼用 SQL 更新、新增、刪除資料庫的內容,這些部分 ORM 都已經幫我們 hanlde 好了。
那裏太快把概念講過去,(只寫「想成」,沒講清楚實際上並不是這樣)
沒注意到這樣會造成誤導,已經更改過敘述並補上一些資料,
不過你舉的例子比較清楚易懂,自己懂和寫出來真的是兩回事。
學習了,謝謝你!