2012-12-17 52 views
2

我最近想寫一個簡單的遷移腳本。我寫道:爲什麼datamapper不更新記錄/檢測髒物?

@entries = Entries.all(:text => /test/) 

@entries.each do |entry| 
    entry.update(:text => entry.text.gsub!(/test/, "no-test")) 
end 

即使update語句返回true,它也沒有保存記錄。我錯過了什麼?

+0

更新後的'entry.save' – 2012-12-17 15:54:27

回答

6

在1.x的系列DataMapper的髒跟蹤是通過對新老屬性值調用#==檢測dirtyness完成。如果對象被突變就位(例如與字符串砰方法),作爲「一部開拓創新」的狀態也被突變不能被檢測到的變化。

基本上以下內部發生:

a = "foo" 
b = a.gsub!("foo", "bar") 
a == b  # => true both a and b refer to the same mutated object 
a.equal?(b) # => true 

在您的例子分配原突變屬性回對象,沒有身份變化=>沒有更新檢測。

如果您通過String#gsub創建新對象,而不是通過String#gsub!變更原始屬性值,那麼您最終會發現可檢測到的更改。

隨着分配一個新的對象有不同的價值會發生以下情況:

a = "foo" 
b = a.gsub("foo", "bar") 
a == b  # => false, loaded state does not equal resource state so change is detected 
a.equal?(b) # => false 

並且對於具有覆蓋所有的情況下,具有相同的值賦給一個新的對象:

a = "foo" 
b = "foo" 
a == b  # => true, no dirtyness detected. 
a.equal?(b) # => false 

希望這解釋了語義差異足以解釋所有類似的情況。

BTW在DataMapper的2.0,我們有一個differend機制,也將趕在地方突變。免責聲明,我是該組件的作者dm-session

+0

非常感謝您的詳細解釋! –

+0

任何理由不接受此答案? – mbj

+0

啊!使用Equals檢測更新的增量 - 我瘋了,試圖找到正確的「搜索關鍵字」,以瞭解數據映射器如何計算出一組精確的記錄,並寫入Master-Detail類域對象。使用枚舉{添加/刪除/更新}或髒標誌看起來不正確。如果你有這方面的資源,請分享 - 謝謝! – Gishu

1

刪除感嘆號。

entry.update(:text => entry.text.gsub(/test/, "no-test"))

當你替換字符串的內容記錄不走髒。你應該重新分配它。

+1

謝謝,現在我明白了爲什麼'!'代表危險'; –

相關問題