2016-01-28 88 views
2

好的,雖然GitHub發生故障,但代碼設計問題:
我總是在Rails應用程序(通常是)中使用非標準REST風格的動作獲得分析癱瘓。Rails中的非REST風格的動作

我有喬布斯,我希望能夠取消(和重新激活)他們。這不像設置複選框那麼簡單;還有其他一些事情需要發生,所以我不能只使用現有的JobsController#update操作。

這裏是我的選擇,因爲我看到它:

只需添加cancelreactivate到現有作業控制器。 的路線是這樣的:

POST /admin/jobs/cancel/:job_id 
POST /admin/jobs/reactivate/:job_id 

(不REST風格;假設這是一個壞主意)

2.createdestroy操作創建JobCancellationsController。 重新激活作業是destroy -ing a JobCancellation資源。

我將使用嵌套的路線按如下:

resources :jobs, except: :show do 
    resource :job_cancellation, only: [:create, :destroy] 
end 

在默認情況下會給我像

一)

POST /admin/jobs/:job_id/job_cancellation 
DELETE /admin/jobs/:job_id/job_cancellation 

我可以整理路線投案自首,而不更改控制器,如下所示:

b)

POST /admin/jobs/:job_id/cancellation 
DELETE /admin/jobs/:job_id/cancellation 

雖然這看起來不太直觀 - '取消'會更好,因爲cancel。所以,我可以改變路線,同時保持控制器相同:

C)

POST /admin/jobs/:job_id/cancel 
DELETE /admin/jobs/:job_id/cancel 

這第一條路現在是有道理的(雖然它不是RESTful嚴格來說),但第二個不.. 。「刪除作業取消」?上述

d)

POST /admin/jobs/:job_id/cancel 
POST /admin/jobs/:job_id/reactivate 

現在的路線是有道理的,但一臉狐疑接近選項1),即使路由自身映射到REST風格的動作:所以你會改變它的東西像JobCancellationsController而不是JobsController中的非REST風格的操作。並且POST /admin/jobs/:job_id/reactivate路由映射到JobCancellationsController#destroy操作似乎非常棒。

爲了避免去年odity與JobCancellationsController#destroy,我可以代替做:

3。與選項2類似,但創建兩個控制器:JobCancellationsController僅限create動作,而JobReactivationsController僅限create動作。

什麼是「正確」的方式來做到這一點?或者至少,哪些是我可以迅速消除的「不正確」方式?有沒有完全不同的,更好的方式,我錯過了?

回答

5

在Ruby澳大利亞鬆弛通道的討論之後,我已經鞏固了意見到如下:

答案

只需添加cancelreactivate現有JobsController

使用此代碼:

resources :jobs do 
    post :cancel, on: :member 
    post :reactivate, on: :member 
end 

創建類似的路線:

POST /admin/jobs/:job_id/cancel 
POST /admin/jobs/:job_id/reactivate 

這是簡單直觀,即使它不是嚴格的REST風格。

(另一種建議的方法是補丁現有update法的取消狀態,但我想這會需要在你的更新方法的條件爲cancels VS常規updates

其他有用的點是在討論

  • 資源配置事情是不是資源出來是一種常見的陷阱,當你被賣「REST是最好的!」 (即,Jobs是資源,但JobCancellations不是真的,所以不要試圖使它們成爲資源)。

  • 如果您不需要刪除作業的功能,則可以使用destroy操作取消作業而不是cancel操作。

  • 海事組織去全REST只有在某些情況下,你是不可能遇到,除非你在一個大公司。

  • 製作一個合理的API。 Rails只是提供了輕鬆執行CRUD的方法。這與寧靜有關,但並非全部。

  • 的REST(或HATEOS)的方式來做到這一點是有/jobs/1234.json包括cancelLink: {url: "url", method: "POST", rel: "link to the docs"}財產

  • ,當我們正在建立我們的API,我們有一個非官方的規則,如果我們不知道該怎麼辦,我們只是複製github所做的,因爲我們喜歡他們的API。我使用了一些根據休息很好設計的「休息」API,但作爲開發人員使用起來很糟糕。更重要的是你A)覆蓋原語,並且B)使用它比你一直遵守REST(或者HATEOS,或者你今天關注的任何東西)更友好。

以上所有的基本指向意見,我總是試圖告訴自己:「這是最重要的是,代碼簡單,易於理解設計patters只給他們幫助你實現這個程度是有用的。目標,如果一個設計模式沒有達到這個目標,那麼很可能你錯誤​​地使用了它,或者將它應用到一個不正確的情況,或者過於僵硬地使用它。

1

在這種特定情況下,爲什麼不只是有

# Cancel a job (handled by your cancellations controller) 
DELETE /admin/jobs/:job_id 

# Likewise, reactivate a job if so instructed by the request body 
PATCH /admin/jobs/:job_id 

有很多的潛力,在一般的「你沒有做休息權」的爭論,我不認爲我真正關心運行進入;這個特殊情況看起來像是一個體面的解決方案。

FWIW,你真的需要允許重新激活同一項工作嗎?要求一旦取消創建新工作可能會更清楚。也許提供一些克隆現有工作的機制。

+0

謝謝。我在Ruby Australia鬆弛頻道上就此進行了很好的討論。建議與你的建議並不遙遠,但有一些額外的信息值得了解。我很快就會把它整合成一個答案。 順便說一句,是的,肯定需要重新激活。 –

+0

幾件事。 (1)取消是錯誤的詞;稱它停用。 (2)作業取消不是資源,而是任務/動作。 (3)我認爲資源是嵌套在作業下的「活動」標誌 - 將其設置爲真或假。 – cliffordheath

+0

是的,這是有道理的cliffordheath。那麼你會有一個JobActiveFlagsController嗎? –