DHH的投影片提到一個概念:
Constraints are liberating (a straight jacket for your mind)
這裡指的 Constraints (制約) 是什麼? 我想指的是 Controller 不出以下七種 action (註) :
class PeopleController < ActionController::Base
# GET /people
def index() end
# GET /people;new
def new() end
# POST /people
def create() end
# GET /people/1
def show() end
# GET /people/1;edit
def edit() end
# PUT /people/1
def update() end
# DELETE /people/1
def destroy() end
end
例如多對多關係。我們以往習慣把加入或刪除關聯的動作放在 UsersController 或 GroupsController 中,如以下的程式碼 :
class Group < ActiveRecord::Base
has_and_belongs_to_mang :users
endclass User < ActiveRecord::Base
has_and_belongs_to_mang :groups
endclass GroupsController < ActionController::Base
# POST /groups/1;add_user?user_id=2
def add_user() end
# POST /groups/1;add_user?user_id=2
def remove_user() end
endclass UsersController < ActionController::Base
# POST /users/1;join_group?group_id=2
def join_group() end
# POST /users/1;leave_group?group_id=2
def leave_group() end
end
用制約的想法之後,我們得把加入或刪除關聯的動作獨立出來了,變成這樣:
class Group < ActiveRecord::Base
has_many :memberships
has_many :users, :through => :memberships
endclass User < ActiveRecord::Base
has_many :memberships
has_many :groups, :through => :memberships
endclass Membership < ActiveRecord::Base
belongs_to :group
belongs_to :user
endclass MembershipsController < ActionController::Base
# POST /memberships?group_id=1&user_id=2
def create() end
# DELETE /memberships/3
def destroy() end
end
透過這樣的 CRUD 技法之後,除了開發時使用統一的風格來寫程式架構之外,意義在於 把對網站的所有操作都變成對某個 Resource (某個URL) 的 HTTP GET/POST/PUT/DELETE 操作 (註)。撰寫 Controller action 的同時也完成了 Web APIs (註),除了可以給使用者瀏覽器之外,我們也可以用 machine client 如 ARes 來操作整個 RESTful 網站系統的任一功能。這在以前幾乎是很花時間跟成本的事啊 : server-side 要特地打造 Web Service,client-side 也必須花時間學習如何使用API,現在只需要遵循 RESTful 可以從 SOAP and WS-* 解放出來… :p
Constraints are liberating 它讓我們更專注在要做什麼。
註: 你會發現 Controller 的這七個 action 中, GET /people;new 跟 GET /people/1;edit 這兩個只需對瀏覽器使用者有作用,所以沒有提供XML(不算是Web APIs)。另外五個 action ( GET /people, GET /people/1 跟 POST/PUT/DELETE) 則同時擔任了Web APIs 跟 回應瀏覽器 的功能。
參考資料:
很详尽