Rails 憑藉「慣例優於配置」與快速開發能力,已從輕量級創業專案延伸至保險、金融等重工業領域。但「選用 Rails ≠ 高品質」。本文從六大面向剖析影響品質的關鍵決策,並說明 Rails 3 如何透過架構改進引導開發者走向正途。
痛點:Controller 承擔 Model 職責 (如關聯物件建立、業務規則)。
# Rails 2.3 前:Controller 處理巢狀屬性
def create
@album = Album.new(params[:album])
@album.photos << Photo.new(params[:album][:photo]) # 應屬 Model 責任
...
end
Rails 2.3+ 解法:accepts_nested_attributes_for
class Album < ActiveRecord::Base
accepts_nested_attributes_for :photos
end
# Controller 回歸單純
def create
@album = Album.new(params[:album])
...
end
原則:Controller 只負責「接收請求、協調 Model、渲染回應」,業務邏輯、資料完整性、關聯管理全歸 Model。
反模式:為下載 PDF 新增 download_pdf action。
# 錯誤:動作非資源導向,PDF 生成邏輯泄露在 Controller
def download_pdf
send_data(generate_pdf(@invoice), :type => 'application/pdf')
end
RESTful 重構:PDF 是 Invoice 的另一種表現形式,屬於 show。
def show
respond_to do |format|
format.html
format.pdf { render :pdf => @invoice.pdf } # 需註冊 Mime::Type
end
end
Rails 3 Router 大幅強化 RESTful 路由 DSL,強迫開發者以資源視角設計 API。
Rails 3 Unobtrusive JavaScript (UJS):
<%= link_to "Delete", album_path(@album), :method => :delete, :confirm => "Sure?" %>
Rails 2 產出 (內嵌 JS,難維護、污染 HTML):
<a href="/albums/1" onclick="if (confirm('Sure?')) { var f=document.createElement('form'); ... }">Delete</a>
Rails 3 產出 (HTML 純淨,行為委派給 rails.js):
<a href="/albums/1" data-confirm="Sure?" data-method="delete" rel="nofollow">Delete</a>
啟示:HTML/JS/CSS 職責分離,前端同樣需要 MVC/模組化架構。
鐵律:資料離使用者越近越快 → 客戶端快取靜態資產,永不快取動態 HTML。
<%= stylesheet_link_tag "application" %>
# 產出: <link href="/stylesheets/application.css?1232285206" ...>
# 時間戳查詢字串 → 檔案更新即失效,安全永久快取
資料庫層面:
includes(:associations) / eager_loadselect(:id, :name)| 威脅 | Rails 內建防護 | 啟用方式 |
|---|---|---|
| Session Fixation | 登入前重置 Session | reset_session 在登入 action 首行 |
| CSRF | 非 GET 請求驗證 Token | protect_from_forgery :secret => "long_random_string" |
| Log 敏感資訊洩露 | 過濾參數不寫入 Log | filter_parameter_logging :password, :credit_card |
| SQL Injection | ActiveRecord 參數化查詢 | 預設啟用,避免手拼 SQL 字串 |
| XSS | View 自動 Escape | Rails 3+ 預設 html_safe 機制 |
案例:電子商務付款頁面效能差,邏輯包含「扣款」+「產生 PDF 收據」。
重構:PDF 非付款核心流程,移至付款成功頁,使用者點擊才產生。
# 原:付款 action 同步產生 PDF → 回應緩慢
# 新:付款 action 僅扣款 → 導向成功頁
# 成功頁提供「下載收據」連結 → 點擊時才異步產生 PDF
洞見:當實作陷入困境,回頭審視「業務邊界是否正確」,往往能以最小變更解決最大問題。
高品質 Rails 應用非靠單一技巧,而是無數微決策的疊加:MVC 單一職責、REST 資源語義、UJS 前端解耦、快取策略、內建安全一行啟用、業務邊界正確。Rails 3 的每項改進 (Router、UJS、ActiveModel、Bundler) 皆在引導這些決策。