Trailblazer 簡介
Trailblazer 位于Rails頂端,是,thin web 服務器的一個層(layer)。它溫和的實施封裝,有直觀的代碼結構,并且提供面向對象的架構。
堅果殼內:trailblazer允許你跟操作數據對象一樣編寫無邏輯模塊,不包含回收,嵌套,驗證或域邏輯。它通過提供一些附加層移除bulky controllers和strong_parameters來承載代碼并完全取代helpers。
請支持我即將出版的新書 Trailblazer - A new architecture for Rails,免費閱讀樣章,讓我知道你的想法。
書中討論了demo application工具。
使命
開拓者(Trailblazer)為您在Rails的各個方面提供Ruby抽象層,它不傳教你。只要你愿意,你可以回退到“Rails通道”模型,單片控制器,全局傭工等,這是不是一件壞事,但讓你分步介紹開拓者的封裝在你的應用程序,而無需重寫它。
Trailblazer是所有關于結構。它有助于重新組織現有的代碼放到哪里不同的關注點在分離類處理更小的組件。形式進入表單對象,視圖是面向對象的MVC控制器,業務邏輯發生在通過完全脫鉤的持久性對象支持專用的域對象。
同樣,你可以選擇你想要的圖層。開拓者并沒有對技術的實現,它提供了經常性在所有類型的Rails應用程序的問題,成熟的解決方案。
Trailblazer沒有“對象和間接的復雜的網絡。”它解決了已經存在多年了干凈的分層架構的許多問題。只使用你喜歡什么。這就是底線。
OOP 概念框架
Trailblazer提供你一個新的,更直觀的文件布局在Rails應用程序中,您文件的結構概念 。
app ├── concepts │ ├── comment │ │ ├── cell.rb │ │ ├── views │ │ │ ├── show.haml │ │ │ ├── list.haml │ │ ├── assets │ │ │ ├── comment.css.sass │ │ ├── operation.rb │ │ ├── twin.rb
文件、類和視圖邏輯上屬于一個 概念 保存在一個地方。 你可以自由使用其他名稱空間中的一個概念。 開拓者試圖保持盡可能簡單,。
體系結構
Trailblazer擴展了傳統的MVC Rails堆棧。 記住,添加層并不一定意味著添加更多的代碼和復雜性。
相反的情況:控制器、視圖和模型成為精益HTTP端點,渲染和持久性。冗余代碼被投入很少的應用程序代碼消除正確的層。
Routing(路由)
Trailblazer使用Rails的路由URL映射到控制器(我們將添加到簡化路由推出)。
Controllers(控制器)
控制器是瘦終端的HTTP。它們分化請求的格式,如HTML或JSON之間并立即派遣一個操作。控制器不包含任何業務邏輯。
Trailblazer提供了四種方法來呈現和調用操作。但在這之前,你需要包括Controllers 模塊。
class CommentsController < ApplicationController include Trailblazer::Operation::Controller
Rendering the form object(喧染表對象)
操作可以填充,并展示他們的表單對象,因此它可以與simple_form和其他形式的助手使用。
def new form Comment::Createend
這將運行操作,但不是它的validate驗證碼。它在控制器然后設置@form實例變量,因此它可以被渲染。
= form_for @form do |f| = f.input f.body
#form 是指對象#new和#edit,只有HTML有動作。
運行操作
如果你不打算保留不同要求的格式,最簡單的就是用#run來操作處理輸入數據。
def create run Comment::Createend
這只需運行Comment::Create[params].
你也可以傳遞你自己的參數。
def create run Comment::Create, params.merge({current_user: current_user})end
一個額外的塊將被執行僅當操作結果是有效的。
def create run Comment::Create do |op| return redirect_to(comments_path, notice: op.message) endend
注意該動作的實例是產生的塊。
一個無效的響應的情況下可以在塊之后進行處理。
def create run Comment::Create do |op| # valid code.. return end render action: :newend
不要忘了,從有效塊return,否則既有效塊和無效的通話之后將被調用。
Responding(響應)
另外,您也可以使用Rails的出色#respond_with讓一個響應處理所要渲染的。操作可以傳遞到respond_with。發生這種情況自動#respond,讓Trailblazer調用操作的第三個方法。
def create respond Comment::Createend
這將只需運行操作和Chuck的情況下進入應答讓后者梳理呈現了什么或者重定向。操作代表各自的調用其內部model。
你還可以在該塊處理不同的格式。這是完全細做,在控制,因為這是端點的邏輯是HTTP特有的,而不是business。
def create respond Comment::Create do |op, formats| formats.html { redirect_to(op.model, :notice => op.valid? ? "All good!" : "Fail!") } formats.json { render nothing: true } endend
傳遞給#respond塊總是執行,無論操作結果的有效性。目標是讓響應處理操作的有效性。
formats對象只是傳遞到#respond_with。
Presenting(介紹)
對于#show模式行為,單純使用HTML頁面或JSON或XML文檔的,#present方法就派上用場了。
def show present Comment::Createend
同樣,這將只運行操作的設置,并提供了模型@model。然后,您可以使用cell或控制器視圖HTML呈現模型。
對于基于文檔的API和非HTTP請求類型的操作將被告知渲染操作使用申述的JSON或XML文檔。
需要注意的是#present還將代替#form(允許它也在#new和#edit使用)作為響應將不會觸發任何渲染。
Controller API(控制器API)
在這三種情況下的實例變量分配:@operation,@form,@model.
Operation(操作)
操作封裝業務邏輯。每高一級域名的功能之一操作使用。不同的格式或環境的子類進行處理。操作對于HTTP無感知的。
class Comment < ActiveRecord::Base class Create < Trailblazer::Operation def process(params) # do whatever you feel like. self end endend
操作只需要執行#process從調用接收參數。
Call style(調用樣式)
最簡單運行的操作是調用樣式。
op = Comment::Create[params]
使用Operation#[]將會返回該操作的實例,在無效操作的情況下,這將引發異常。
注意如何可以容易用于測試工廠。
let(:comment) { Comment::Create[valid_comment_params].model }
使用操作作為測試工廠是Trailblazer的基本概念,以消除冗余的buggy(越野車)在測試和手動工廠。
Run style(運行樣式)
您可以手動運行的操作,并使用相同的塊語義在控制器中。
Comment::Create.run(params) do |op| # only run when valid.end
當然,這并不拋出異常,而只是當操作無效時跳過該塊。
Validations(驗證)
操作通常有一個表單對象,它僅僅是一個Reform:: Form類。所有記錄在Reform的API可以應用和使用。
該操作利用表單對象來使用#validate方法。
class Comment < ActiveRecord::Base class Create < Trailblazer::Operation contract do property :body, validates: {presence: true} end def process(params) @model = Comment.new validate(params[:comment], @model) do |f| f.save end end endend
該contract(又名表單)在::contract塊中定義。可以實現嵌套形式,默認值,驗證,以及其他一切Reform提供的。
該情況下的一個有效的形式為#validate塊被調用。它接收填充表單對象。您可以使用表單來保存數據或寫你自己的邏輯。
從技術上來說,真正發生在Operation#validate如下。
contract_class.new(@model).validate(params[:comment])
從Reform而言,這是一個熟悉的工作流程。驗證與模型無關。
Models(模塊)
模塊的持久性可以用你喜歡的任何ORM來實現,比如ActiveRecord的或DataMapper的。
在Trailblaze,模塊是完全空的,僅配置數據庫相關指令和協議。沒有業務邏輯是允許在車型。只有操作,視圖和組件可以直接訪問模塊。
Views(視圖)
查看渲染可以使用從Rails的知名控制器發生。這絕對是簡單的視圖。
更復雜的UI邏輯發生在視圖模型的cells中發現的。視圖模型替換助手。
1.HTTP API消費和渲染API文檔(如JSON或XML)是通過轟鳴聲和表示的完成。他們通常繼承合同的模式。
2.測試待測試主要是操作和查看模型,因為它們封裝你的應用程序的終結點行為。作為一個好的副作用,工廠通過簡單的操作要求更換。
Controller API (控制器API)
Normalizing params
覆蓋#process_params!添加或操作運行之前刪除值PARAMS。這就是所謂的在#run,#respond和#present。
class CommentsController < ApplicationController # ..private def process_params!(params) params.merge!(current_user: current_user) endend
這集中PARAMS正常化,在每一個動作里,并不需要你手動。
Different Request Formats(不同的請求形式)
控制器的幫手#present和#respond自動通過request body(請求主體)進行操作并經由參數hash。由操作的建立者決定哪個類要實例化。
class Create < Trailblazer::Operation builds do |params| JSON if params[:format] == "json" endend
[注意,它很快就會提供一個模塊。]
Operation API(操作API)
CRUD Semantics(增刪改查語義)
你可以作為Trailblazer(先驅者)為你所使用的CRUD模型去查找和創建模型。
require 'trailblazer/operation/crud'class Comment < ActiveRecord::Base class Create < Trailblazer::Operation include CRUD model Comment, :create contract do # .. end def process(params) validate(params[:comment]) do |f| f.save end end endend
你必須告訴CRUD模型類,什么行為能實現使用::model。
注意你不必通過@modelto驗證有效性。 而且, @model的被創建是自動化的并通過Operation#model訪問。
在繼承操作上,你可以重載方法, 并只要使用::action就好。
class Update < Create action :updateend
另一個操作是:find(它目前的做法和:update一樣) 通過params[:id]這種方式找到模型。
后臺處理
在Sidekiq (ActiveJob即將支持)中進行操作,你只需要包含Worker模塊:
require 'trailblazer/operation/worker'class Comment::Image::Crop < Trailblazer::Operation include Worker def process(params)# 將會異步方式運行 endend
渲染操作表單
你可以通過::present來訪問操作表單
Comment::Create.present(params)
上面代碼,運行操作的#process方法,而不包含驗證代碼塊,也不用返回約定(return the contract?)。
標記操作為無效
有時你不需要一個表單對象,但是需要操作的有效行為。
def process(params) return invalid! unless params[:id] Comment.find(params[:id]).destroy selfend
#invalid!在默認失效時返回自身,但是可以接受任意結果。
Worker::FileMarshaller: needs representable 2.1.1 (.schema)
測試操作
自動加載
如果不喜歡顯式地require,你可以使用自動加載。
只需要將
require 'trailblazer/autoloading'
添加到config/initializers/trailblazer.rb,這樣文件就會自動加載。
為何?
-
通過概念來組合代碼、視圖、資源,能提高應用的可維護性。直觀的文件布局可以使開發者快速地了解應用的組織結構。
-
分層封裝將測試組件完全隔離,這樣調試起來不會那么煩惱了。一旦你確定表單和視圖都是OK的,那問題肯定在解析的代碼里。
-
Trailblazer慢慢地推動你進行封裝,這促使代碼的可重用性不斷提升。不再有冗余的helper,取而代之的是簡潔的繼承。
-
(使用Trailblazer)從此再也不怕被ActiveRecord的大量API驚嚇住。持久性和領域的分離自然地使模型的API更小、更非破壞性。