2014-02-19 59 views
27

以下職位是基於on Rails的4軌道4 [最佳做法]嵌套資源和淺:真

實際上,我在尋找有關的多個嵌套資源良好的最佳實踐(大於1),和選項淺:真。

首先在我的路線,有這樣的:

resources :projects do 
    resources :collections 
    end 

相關的路線是:

project_collections GET /projects/:project_id/collections(.:format)   collections#index 
         POST /projects/:project_id/collections(.:format)   collections#create 
new_project_collection GET /projects/:project_id/collections/new(.:format)  collections#new 
edit_project_collection GET /projects/:project_id/collections/:id/edit(.:format) collections#edit 
    project_collection GET /projects/:project_id/collections/:id(.:format)  collections#show 
         PATCH /projects/:project_id/collections/:id(.:format)  collections#update 
         PUT /projects/:project_id/collections/:id(.:format)  collections#update 
         DELETE /projects/:project_id/collections/:id(.:format)  collections#destroy 
       projects GET /projects(.:format)         projects#index 
         POST /projects(.:format)         projects#create 
      new_project GET /projects/new(.:format)        projects#new 
      edit_project GET /projects/:id/edit(.:format)       projects#edit 
       project GET /projects/:id(.:format)        projects#show 
         PATCH /projects/:id(.:format)        projects#update 
         PUT /projects/:id(.:format)        projects#update 
         DELETE /projects/:id(.:format)        projects#destroy 

我有關嵌套資源的限制的文件中讀取資源不應該嵌套超過1級。

來源:http://guides.rubyonrails.org/routing.html#limits-to-nesting 好的。然後,就像文件說的那樣,我會在我的路線中使用「淺」。

shallow do 
    resources :projects do 
      resources :collections 
    end 
end 

相關的路線是:

project_collections GET /projects/:project_id/collections(.:format)  collections#index 
         POST /projects/:project_id/collections(.:format)  collections#create 
new_project_collection GET /projects/:project_id/collections/new(.:format) collections#new 
     edit_collection GET /collections/:id/edit(.:format)     collections#edit 
      collection GET /collections/:id(.:format)      collections#show 
         PATCH /collections/:id(.:format)      collections#update 
         PUT /collections/:id(.:format)      collections#update 
         DELETE /collections/:id(.:format)      collections#destroy 
       projects GET /projects(.:format)        projects#index 
         POST /projects(.:format)        projects#create 
      new_project GET /projects/new(.:format)       projects#new 
      edit_project GET /projects/:id/edit(.:format)     projects#edit 
       project GET /projects/:id(.:format)       projects#show 
         PATCH /projects/:id(.:format)       projects#update 
         PUT /projects/:id(.:format)       projects#update 
         DELETE /projects/:id(.:format)       projects#destroy 

主要的區別我看到的是收藏的 「秀」,這樣一句:

collection GET /collections/:id(.:format)      collections#show 

所以,如果我我是對的,展示動作的鏈接是:

<%= link_to 'Show", collection_path(collection)%> 

,應該返回類似這樣的內容:「http://example.com/collections/1

但是! 2件事:

  • 這是行不通的。我得到的是「http://example.com/projects/1」。 WTF?
  • 即使是工作,它實際上是非常糟糕的,因爲我失去了REST基本是說:「收藏是項目的孩子,那麼URL應該是‘本地主機/項目/ 1 /收藏/ 1’

我不明白什麼是淺薄的利益,如果它是放鬆休息行動的巨大優勢。什麼是興趣?什麼是放鬆「顯示」行動的興趣?我已經發布到SO,但唯一的評論我得到的是「這是正常的東西。」跆拳道?在這是一個正常的行爲,以「從其他API刪除」行動?

我轉載了一箇中性項目的問題,以確保我沒有做有問題,併發生同樣的問題。所以,對於輔助者來說,使用淺度可能會比較方便,但對於其他人來說,這並不方便,因爲您放棄了「一個集合嵌套到一個項目中的所有興趣,所以這反映在URL中」。

我不知道是否有另一種方法可以做到這一點,淺的確允許助手具有更多的靈活性,但它是錯誤的,它是休息兼容的。那麼,是否有機會讓「幫助者」工作(擁有「nested3_path(collection)」而非「nested1_nested2_nested3([nested1.nested2.nested3,nested1.nested2,nested1])」,並保持「 url部分「並保持」nested1/123/nested2/456/nested3/789?

謝謝!

+0

您是否嘗試過重新啓動服務器以使路由生效? 據商務部 '資源:帖子,淺:真正做 資源:評論 end' 會產生 '資源:帖子做 資源:評論,除了:[:顯示,編輯,:更新, :destroy] end 資源:評論,只:[:顯示,:編輯,:更新,:銷燬]' 你好像在做什麼 – jamesy829

+0

確實必須重啓服務器才能使路由生效。 – 0112

回答

20

我不認爲Rails提供任何內置方式讓URL使用完整的層次結構(例如, /projects/1/collections/2),但也有快捷助手(例如collection_path而不是project_collection_path)。

如果你真的想這樣做,你可能會推出自己的定製幫手類似如下:

def collection_path(collection) 
    # every collection record should have a reference to its parent project 
    project_collection_path(collection.project, collection) 
end 

但是,這將是非常麻煩的每個資源做手工。


我覺得用shallow路線背後的想法是最好的文檔總結:避免深度嵌套(如上推薦)

的一種方法是產生 範圍的收集行動在父項下,以獲得層次結構的感知 ,但不嵌套成員操作。換句話說, 只有建立與信息 最小量的路由唯一地標識資源

來源:http://guides.rubyonrails.org/routing.html#shallow-nesting

因此,儘管這可能不是REST規範(像你說的),你不會丟失任何信息,因爲每個資源都可以唯一標識,並且您可以在假設您的關聯設置正確的情況下恢復層級。

+0

雖然它沒有內置到Rails,[繼承資源](https://github.com/josevalim/inherited_resources)(IR)有嵌套和幫手,可能有幫助。如果僅僅是少數情況下使用IR,它可能是好的,而不是使用IR,它也可以根據你的需要限制或複雜控制器的實現/調試。 –

2

水平

,你必須在你的嵌套的資源只能用1級的概念是唯一真正適用於系統的設計:

相應的路線助手將publisher_magazine_photo_url, 要求您在所有三個級別指定對象。事實上,這種 情況混亂,以至於通過了Jamis巴克 一個流行的文章提出了拇指良好的Rails設計的原則:

相信的Rails仍然可以處理多個層面,雖然它不是從可用性的角度來看

推薦

雖然我見過淺以前用過,我從來沒有用它自己

從看documentation,它似乎很淺,有一個相當模糊的目的(我不知道它爲什麼在那裏)。問題是你沒有公開傳遞post_id參數到你的控制器,讓你加載collection沒有一個重要的參數

我會猜測(這只是猜測),目的是通過你的參數需要在幕後,所以你留下了一個公共「淺」路線:

#config/routes.rb 
resources :projects do 
    resources :collections, shallow: true 
end 

我會想象你會得到一個網址助手是這樣的:

collection_path(project.id, collection.id) 

這會出來的domain.com/collection/2

+0

是的,你是正確的路線,但這對我的問題沒有多大幫助=/ – Erowlin

10

因爲有一個Collection是一個id,它是多餘的嵌套項目下的路徑除了indexcreate行動。

有一個關於URL的規則,其中只有一個URL應該是GET(200)給定資源的URL,如果有其他URL,您應該重定向到它。所以你可能有一條路線/projects/:id/collections/:collection_id重定向到/collections/:collection_id

在你的情況下,一個集合與一個項目綁定,但這對於所有的關係並不一定是正確的。一旦你有了:collection_id,你就不需要參考Project的上下文來訪問它。

+0

是的!謝謝!我一直在尋找淺層路線目的的基本解釋!文檔中的假設是:您已經知道這一點。從其他一些答案來看,其他很多人都不知道!你說的是,如果你是例如編輯一個評論:id,它沒有任何意義嵌套在項目下,因爲評論:ID是獨立於項目ID。淺薄只是清理路線來反映這一點。 – Colin

2

雖然它可能會使事情複雜化,如果您只需要某些型號,可能需要檢查Inherited Resources(IR)。它支持資源嵌套,多態屬於它,並且可以自動生成你正在尋找的較短的路徑和url幫助器方法。你沒有聽說IR的原因是它的原作者和一些其他開發者已經放棄了它,因爲在擴展你的控制器時出現了複雜問題。但是,它仍然有一個社區,我們試圖擴展它更多,並更多地關注使用Irie控制器擴展的簡易性。

Rails中的「最佳實踐」取決於您與誰交談。

Rails傳統上主要針對(非嵌套)資源的基本CRUD。是的,它允許檢索和更新嵌套的資源,但假設不會經常發生。

但是,Rails社區已經出現的方法是ActiveModel::Serializers/json-api方法。在這種情況下,通常不會發生多個級別的資源嵌套,並且嵌套的資源是鏈接列表或側載的小型資源的子版本,然後您可以在該資源上查詢以獲取更多數據。這也被Ember/Ember Data所包含。

還有roar和一些其他項目旨在實現一些更接近於他們對Roy Fielding最初的REST願景的理解。

我認爲這取決於你的設計和你需要什麼。如果效率是一個目標,那麼額外的時間發展爲明確的並且築巢更多的時間可能會得到回報。例如,我們目前使用AngularJSIrie。但每一個他自己。

至於最後一點,請務必避免在查詢中使用includes(...)(或類似的)進行n + 1查找,否則所有嵌套操作都會影響性能。

1

From this answer它似乎很淺薄的路線有點違抗Rails,IMO的慣例。

我認爲你不需要顯式路徑助手來顯示路徑。 link_to助手應該能夠從對象的to_param方法中推斷出它。

#your helper becomes 
link_to "show", collection 

如果以上述方式使用助手,則可能需要將父資源的嵌套ID傳遞給助手。

link_to "show", collection_path([project, collection])