2012-07-13 50 views
0

我有另一個模型的潛在多個孩子家長模型和嵌套屬性的Rails的形式。爲什麼直接操縱Rails表單參數散列考慮代碼味道?

子模型具有在邏輯操作作爲陣列的屬性,但是序列化使用的Rails一個YAML串內置serialize方法。

在形式,我顯示該陣列的每個單獨的構件,使得用戶可以選擇性地刪除成員。

的問題,當用戶銷燬所有成員發生。表單不會將任何參數值傳遞給Rails控制器,並且在調用UPDATE操作時,它將忽略該屬性,因爲在形式參數散列​​中沒有鍵。這當然是一個已知的問題,比如複選框,所以Rails會爲每個複選框自動放置2個複選框HTML元素,其中一個隱藏,只有在複選框被選中時纔會處理。

我不處理這裏的複選框,而是隱藏輸入文本字段。

我實現的解決方案是直接操作params哈希表在控制器的UPDATE操作,像這樣:

params[:series][:time_slots_attributes].each { |k,v| v[:exdates] ||= [] } 

這被認爲是代碼味道?

我應該代替添加一個額外的隱藏字段被禁止,只被啓用,當用戶刪除最後一個成員?這個解決方案也適用,但對我來說似乎很笨拙。

+0

@Deefour,不解決這個問題。問題是,當通過UPDATE操作處理params哈希時,需要將一個空數組寫入數據庫。我想我可以檢查一下參數值是否存在,如果不存在,我可以根據需要分別更新每個孩子的屬性。 – Ben 2012-07-13 15:34:52

+0

類似這樣的:'params [:series] [:time_slots_attributes] .each_with_index do | attribs,idx | @ series.time_slots [idx] .update_attribute(:exdates,[])除非attribs [1] .has_key?(:exdates) end' – Ben 2012-07-13 15:52:22

+0

你問是否是代碼異味;這是我回應的唯一的事情。 – deefour 2012-07-13 15:55:26

回答

0

這遠不是一個詳盡的答案......但考慮到這個問題後,我可以看到的一個問題是,如果將來的表單構建時會利用相同的UPDATE操作,將會發生意外的行爲,這違反了原則最少的驚喜。如果在以後的時間內構建了第二個表單,該表單不會爲exdates屬性更改值(因爲它不會傳遞它們),但UPDATE操作無論如何都會將空數組寫入該屬性。

我已經決定通過添加一個帶有真布爾值的單個隱藏表單字段來解決此問題,並且稍後在將所有時間片過期設置爲空數組之前檢查此值。這樣,如果未來的開發人員創建一個利用串行控制器的UPDATE操作的新表單,它們將不會將其過期的意外行爲設置爲空數組。如果他們想要以他們的形式處理過期,他們需要具有相同的具有真實價值的隱藏表單字段。這似乎是一個更簡單的解決方案,然後爲exdates,migration和AR關聯添加一個類和表,並添加另一層嵌套屬性,這樣我就不僅具有父級和子級屬性,還可以放置父級,子級和孫級。這個解決方案有點像Rails hack用於處理帶有第二個隱藏複選框字段的複選框。

1

這在NestedAttributes模塊中通過允許「_destroy」參數來觸發呼叫銷燬用於該特定嵌套屬性處理:

http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for

如果你不使用嵌套的屬性(你可能應該是,這是相當整齊了很多的情況下),然後是的,你必須自己handroll東西,通過制定哪些值應該已目前和做一些特別的東西。

+0

我們使用的參數爲:allow_destroy => true,但是這隻適用於複選框表單域嗎? – Ben 2012-07-13 18:15:32

+0

也許我在這裏感到困惑,但我認爲「_destroy」參數是銷燬子對象,而不是嵌套屬性?我並沒有試圖摧毀整個兒童對象。我試圖讓用戶堅持一個數組屬性,該屬性或者(a)不變,(b)改變但仍然有值,或者(c)不再有值。 (a)和(b)不是問題。 (c)在某個給定屬性的所有輸入標籤都被禁用時不起作用,該屬性從不出現在params散列中,因此不會對該屬性進行任何更改。 – Ben 2012-07-13 18:21:39

+0

我應該補充一點,我的示例使用父級和子級模型的事實是不相關的。同樣的問題出現在一個簡單的單一模型表單中。我的例子是從一個真正的當前問題中選擇的,這個問題偶然出現在使用嵌套屬性的表單中,但是與問題無關。 – Ben 2012-07-13 18:51:32