我已經開始意識到Rails中的「瘦控制器」哲學,它說業務邏輯不應該在控制器中,但他們應該基本上只負責調用一些模型方法,然後決定渲染/重定向什麼。將業務邏輯推入模型(或其他地方)可以保持行爲方法的清潔(並避免在控制器的功能測試中存留長鏈ActiveRecord方法)。瘦的控制器傳遞分層/嵌套的數據來查看
我跑過的大多數情況都是這樣的:我有三個模型,Foo
,Bar
和Baz
。他們每個人都有一個定義的方法或範圍(稱爲filter
),將對象縮小到我要找的位置。一個瘦小的操作方法可能如下:
def index
@foos = Foo.filter
@bars = Bar.filter
@bazs = Baz.filter
end
不過,我碰到的,其視圖需要顯示更多的分層數據結構的情況。例如,Foo
has_many bars
和Bar
has_many bazs
。在視圖(通用「儀表板」頁面)中,我將顯示類似這樣的內容,其中每個foo
,bar
和baz
已按照某些標準過濾掉(例如,對於每個級別,我只想顯示active
個) :
Foo1 - Bar1 (Baz1, Baz2)
Bar2 (Baz3, Baz4)
-----------------------
Foo2 - Bar3 (Baz5, Baz6)
Bar4 (Baz7, Baz8)
爲用戶提供其需要的數據來看,我最初的想法是把一些瘋狂像這樣的控制器:
def index
@data = Foo.filter.each_with_object({}) do |foo, hash|
hash[foo] = foo.bars.filter.each_with_object({}) do |bar, hash2|
hash2[bar] = bar.bazs.filter
end
end
end
我推下來,以Foo
模式,但這並不好。這看起來不像是一個複雜的數據結構,可以將其分解爲單獨的非ActiveRecord模型或類似的東西,它只需要在每個步驟中應用一個非常簡單的過濾器即可獲取一些foos
及其bars
及其bazs
。
從控制器向視圖傳遞像這樣的分層數據的最佳實踐是什麼?
什麼,如果你只是過濾並急於加載模型,然後擔心在您的視圖中的演示文稿?從我所知道的情況來看,你的控制器方法只是將已經正確的結構重新打包成哈希......如果我錯過了某些東西,我會很抱歉。 –
@DamienRoche:我可能會錯過一些簡單的事情,但我無法想出一種方法來加快考慮到每個步驟的範圍的相關數據。我嘗試了'Foo.filter.includes(:bars).merge(Bar.filter).all'的初始步驟,但在'default_scope'中使用的列有一個模糊的列引用錯誤。閱讀更多使它聽起來像'includes'只能在最簡單的情況下與'merge'一起使用。有什麼我失蹤? – jrdioko
您可以像這樣熱切加載數據:'@ foos = Foo.filter.includes(bars:[:baz])''。 – jokklan