Posted by
在上一篇文章裡稍微提到了ActiveRecord能讓你不需寫SQL語法便能快速地存取資料,(事實上我只提到了讀取的部份,寫入其實也相當簡單,依樣畫葫蘆,只是使用的method不同罷了)這篇便來談談在ActiveRecord裡,是如何處理Model與Model之間的關係。
平常我們在描述兩個資料表之間的關係,通常可能會說兩張table是一對一、一對多、或是多對多,而在ActiveRecord裡,兩個Model之間的關係主要以上述的三種方式來定義。
延續上一篇文章中我所建立的三個model: User, Video, and Comment,這三個model之間的關係如下:
看這樣的描述,如果是尚未接觸過Ruby on Rails或是ActiveRecord的讀者一定會感到疑惑,根本聽不懂我在說什麼嘛!請看下列三段程式碼,分別是上述三個Model的程式:
#Model: rails_app/app/models/user.rb class User < ActiveRecord::Base has_many :videos has_many :comments end
#Model: rails_app/app/models/video.rb class Video < ActiveRecord::Base has_many :comments belongs_to :user end
#Model: rails_app/app/models/comment.rb class Comment < ActiveRecord::Base belongs_to :user belongs_to :video end
看出什麼了嗎?只要使用很直觀的has_many, belongs_to這樣的method便可以輕鬆定義Model之間的關係。
接著,我們還必須仰賴migration替我們新增對應的資料表或欄位,在上一篇文章中已經完成了User migration的程式:
#Migration: rails_app/app/db/migrate/001_create_users.rb
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.column :name, :string, :null => false
t.column :email, :string, :null => false
t.column :password, :string, :null => false
t.column :nickname, :string, :null => false
t.column :memo, :text
t.column :created_at, :datetime
t.column :updated_at, :datetime
end
end
def self.down
drop_table :users
end
end
在上一篇文章中,除了self.up、self.down兩個method之外,我並沒有交代其他程式碼所代表的意義,這邊稍微補充一下
接下來我們要繼續完成與Video、Comment這兩個model相關的migration。migration檔案通常是由generator在建立model的同時,就會自動新增一個migration的檔案,而generator也可以單獨產生一個migration file讓你對資料庫的schema進行改變。
#Migration: rails_app/app/db/migrate/002_create_videos.rb
class CreateVideos < ActiveRecord::Migration
def self.up
create_table :videos do |t|
t.column :title, :string, :null => false
t.column :description, :text
t.column :user_id, :integer
t.column :created_at, :datetime
end
end
def self.down
drop_table :videos
end
end
#Migration: rails_app/app/db/migrate/003_create_comments.rb
class CreateComments < ActiveRecord::Migration
def self.up
create_table :comments do |t|
t.column :content, :text
t.column :user_id, :integer
t.column :video_id, :integer
t.column :created_at, :datetime
end
end
def self.down
drop_table :comments
end
end
從上面的Migration可以發現下列兩點:
從上一篇文章透過generate指令來產生model、migration files,到本篇文章我們實際去修改上述的檔案內容,如果熟練大概三分鐘就可以完成,接下來便可以開始感受到ActiveRecord所帶來的高生產力與享受:D
做完上述動作之後,我們便要將定義好的table schema寫入資料庫裡面,在Rails的目錄結構裡面,config/database.yml便是在定義資料庫的相關設定值。設定資料庫的動作一般是在建立好Rails Project便該完成的,這算是開發Rails project的前置動作之一,那為甚麼我到現在才說咧?其實只是我忘了先講怎麼建立專案、怎麼設定資料庫罷了.....以後如果要把這個系列彙整起來給Rails新鮮人看,再寫一篇好了XD
關於Rails Project的前置動作可以參考午夜盧比人Winson寫的「My Rails Way」,裡面提到的技巧都相當實用,像是第一點提到的
為了節省時間,我通常會維護一個叫做sample的Rails project,裡面把簡易的帳號、密碼、登入做起來,以及設計一個model,也把他的tag、comment功能作起來,並把相關的測試案例寫好、常用的外掛裝起來,然後整包壓成一個sample.zip檔。
倘若資料庫已經設定好,接下來會使用到「rake」指令來將我們規劃好的schema寫入資料庫裡面,指令如下:
rake db:migrate
通常會得到下面的結果:
deduce@nccu:~/test$ rake db:migrate (in /home/deduce/test) == CreateUsers: migrating ====================================== -- create_table(:users) -> 0.0170s == CreateUsers: migrated (0.0174s) ============================= == CreateVideos: migrating ===================================== -- create_table(:videos) -> 0.0090s == CreateVideos: migrated (0.0094s) ============================ == CreateComments: migrating =================================== -- create_table(:comments) -> 0.0089s == CreateComments: migrated (0.0093s) ==========================
如果沒有出現錯誤訊息就代表資料表皆成功建立,接下來我們便可以開始使用ActiveRecord來對資料庫進行各種關聯式的存取動作!
註:實在是有點拖稿,不過我寫這些文章是希望可以盡量淺白,所以盡量詳細、盡量簡單,一樣,有任何錯誤或建議請多指教。