2010-09-14 61 views
1

我的Rails應用程序有許多表單。當喬使用我的應用程序時,我希望每個表單都能爲他提供即時視覺反饋,以確定每個字段的輸入是否有效。一個字段檢查他的電子郵件地址的格式 - 非常簡單。但是另一個允許他將當前資源與其他資源相關聯,並且適用複雜的業務規則。如果表單不完整或無效,我想阻止Joe前進,例如禁用「提交」按鈕。在執行AJAX服務器端驗證時保持RESTful?

我可以通過編寫在瀏覽器中進行驗證的JavaScript來複製出現在我的Rails代碼中的驗證。但這種味道很糟糕 - 任何時候商業規則都會改變,我需要在兩個地方用兩種不同的語言和兩套測試來更新它們。

或者我可以添加一個單一的方法到控制器的資源稱爲'驗證'。它將接受AJAX請求中的表單數據,並返回可用於Joe形式的響應,以提供實時驗證反饋。與「創建」操作不同,「驗證」操作不會改變服務器的狀態。 「驗證」的唯一目的是提供驗證響應。

兩難處境是我不喜歡在Rails中向RESTful控制器添加操作。但我更喜歡在兩種不同的上下文中重複驗證代碼的想法。

我注意到this SO question,這涉及到這個問題。但我對插件或技術不感興趣。我也不認爲這個問題必須Rails特定。我更感興趣的是如何在Web應用程序中最好地處理這類問題。

我還注意到this SO question,它不包括維護RESTful體系結構的約束。

鑑於需要在Web應用程序中動態驗證具有複雜業務規則的表單數據,並且希望維護類似REST的服務器體系結構,那麼同時完成這兩項任務的最簡潔,最可維護的方法是什麼?

+0

在正統的REST體系結構中,有些東西沒有意義。不過,達雷爾的回答很不錯。 – gmoore 2010-09-14 17:29:26

+0

vise和Darrel的解決方案都可以工作。 Vise的解決方案假定您已經在處理複雜的業務邏輯的模型中擁有自定義驗證功能,這不是一個錯誤的假設。 Darrel的解決方案更加靈活,但維護成本更高。 – 2010-09-14 19:19:35

回答

1

我希望我的理解正確,但您可以將JavaScript請求發送到相同的創建操作。例如:

def create 

    @data = DataObject.new(params[:data]) 

if request.xhr? 
    response = @data.valid? ? { :success => true } : { :errors => @data.errors } 
    render :json => response 
    return 
    end 

    # @data.save etc.. 

end 

實際上,我使用的多步向導是這樣的(一個頁面的形式,隱藏CSS部分)。

+0

有趣的想法。這不會阻止基於JSON的Web API將來的工作嗎?另外,不要爲了POST請求的含義而破壞其他RESTful約定 - 也就是在服務器上創建資源? – 2010-09-17 03:51:57

+0

如果您願意,您可以隨時擴展to_json方法。我也很肯定你會使用後期,如果你也有一個驗證方法。事實是驗證方法類似於創建很多。請記住,這種方法不包含任何編輯操作,如果您有多個具有相同要求的控制器,它也不會工作得太好。所以,如果你的要求很簡單,並且你想要避免過度工程,而沒有冒昧地離開其他原則,那麼我認爲它很好。 – vise 2010-09-20 20:40:54

2

我認爲在創建驗證程序「處理資源」時沒有問題,驗證程序可以接受實體並確保它通過所有驗證規則。

你可以做到這一點無論與全球驗證

POST /validator 

在驗證會有標識傳遞的代表性和執行相應的規則,或者您可以創建子資源,

POST/foo/validator 

由於只要這些URL是通過超媒體發現的,並且要驗證的完整表示形式作爲請求的主體傳遞,我看不到任何REST約束被違反。

+0

我簡單考慮了這個想法。你將如何緩解過度的條件邏輯來測試控制器的create動作中的資源類型(比方說12個資源使用了這個驗證器資源)?也許一個將資源類型映射到方法的散列表? – 2010-09-17 03:55:16

+1

@Rich就我個人而言,我會去子資源路線,以避免這個問題。 – 2010-09-17 05:36:13

0

你是對的不重複的客戶端(JavaScript的)和服務器端驗證邏輯)。但是添加驗證資源還會增加維護工作量並降低服務器網絡呼叫的成我喜歡在客戶端進行基本驗證(更好的用戶體驗)以及服務器端的數據一致性。

爲什麼不用模型附加驗證元數據,然後生成用於驗證的表單+ javascript。在最終的提交中,您還會根據模型在服務器端進行最終驗證。

我相信Ruby有一些通用的驗證邏輯是可能的。我想也可以重用一些現有的驗證框架。