我最近想寫一個簡單的遷移腳本。我寫道:爲什麼datamapper不更新記錄/檢測髒物?
@entries = Entries.all(:text => /test/)
@entries.each do |entry|
entry.update(:text => entry.text.gsub!(/test/, "no-test"))
end
即使update語句返回true,它也沒有保存記錄。我錯過了什麼?
我最近想寫一個簡單的遷移腳本。我寫道:爲什麼datamapper不更新記錄/檢測髒物?
@entries = Entries.all(:text => /test/)
@entries.each do |entry|
entry.update(:text => entry.text.gsub!(/test/, "no-test"))
end
即使update語句返回true,它也沒有保存記錄。我錯過了什麼?
在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。
刪除感嘆號。
entry.update(:text => entry.text.gsub(/test/, "no-test"))
當你替換字符串的內容記錄不走髒。你應該重新分配它。
謝謝,現在我明白了爲什麼'!'代表危險'; –
更新後的'entry.save' – 2012-12-17 15:54:27