這一篇的重點也是 Object-Oriented View。因為篇幅太長所以再拆一篇。
16. Form Builder
有時候我們為了排版 Form,不得不在 Form 裡面也穿插一些 HTML 作 styling。
但要寫十幾遍 <div class="field">
是一件很煩人的事。我們最希望的是,其實 View 裡面只要這樣寫就 OK 了:
這樣的煩惱可以透過客製 Form Builder 解決:
其他 Form Builder
不過現在還需要自己寫 Form Builder 嗎?其實機會蠻少了。主要的原因是如熱門的 Framework:Bootstrap 有專屬的 gem bootstrap_form。而 simple_form 也提供 template,透過 API 就可以輕鬆客製出一個 Form Builder。
17. Form Object (wrap logic in FORM, not in model nor in controller)
Form Object 是一個比較新的概念。它的想法是,其實表單的邏輯驗證不應該發生在 Model 裡面也不應該發生在 Controller 裡面。
我們可以重新設計一個 Form Object,使用 ActiveModel 的部份 API 將邏輯重新包裝,塞進 Form Builder 裡面:
( 詳細手法可以見這篇文章:Form-backing objects for fun and profit )
這巧妙的解決了一些問題。比如讓人很煩的 massive assignment issue( 其實使用 strong_parameter 也會讓人心情煩躁)。而且 strong_parameter 並沒有辦法解決這樣的問題:
有時候我們必須要在註冊表單上,多加一個 check_box
,確認使用者同意註冊條款。而 controller 就會變得這麼噁心。
而這麼噁心的 controller 如果又再加上 captcha 或是一些客製選項,那就又會變得更恐怖了。不過 Form Object 的設計門檻也不是很低。
所以 cells 的作者又推出了這麼一個 Gem : Reform,簡化 Form Object 的包裝。
Reform (Decouples your models from form validation, presentation and workflows.)
透過 Reform,剛剛的 Logic 可以被簡化成:
而 controller 裡面又可以重新變會成漂漂亮亮的一層 if/else :
18. Policy Object / Rule Engine (centralize permission control)
這是這一個系列的最後一招。在設計 Application 的時候,我們常要面對權限的設計封裝問題,如:
當權限只有 current_user
時還沒有什麼問題。不過權限通常是會膨脹下去的:
多一個 admin?
還不打緊,但事情往往沒那麼簡單,過不久可能又會生出一個 moderator?
整串邏輯就變得又臭又長。最麻煩的是除了 View 之外,Controller 其實也是需要配合權限檢查的:
Cancan (Authorization Gem for Ruby on Rails)
cancan 是最常被想到的一個整理的招數。透過 Rule Engine 的結構,整理權限:
我之前曾經寫過一個 Cancan 系列,如果你有興趣深入把玩 Cancan 的話,以下是系列連結:
Pundit (Minimal authorization through OO design and pure Ruby classes)
不過 cancan 這種 Rule Engine 式的設計常被開發者嫌過度笨重。最近還新誕生了一種設計手法,利用 Policy Object 對於權限進行整理,其中有一個 gem : pundit 算做得蠻不錯的。
Pundit 的想法是把單獨的一組 logic 抽取出來,放在 app/policies
下。
而在 View 裡面單獨使用 policy object 驗證:
controller 裡面也只要 include Pundit
,就可以套用邏輯。
Maintainable Rails View 系列文目錄