2012-01-02 53 views
0

我有更新模型屬性的代碼,然後調用save!。 A Rails.logger.info調用顯示模型認爲它具有新值。但由save!調用執行的SQL寫入將舊值寫入數據庫。Rails 3:object.save將舊值寫入數據庫

起初,當我撥打save!時,根本沒有寫入任何數據庫。我認爲這個對象並沒有想到它的值因爲某種原因而改變了:changed?返回false,所以我用_will_change!通知來強制寫入。但現在它正在寫作,但有了舊的價值。

這不會發生在「rails console」命令行中:在那裏我可以更新該屬性,它將返回真實的changed?,並讓我保存成功。

摘錄自服務器日誌如下。請注意,該對象認爲它有log_ids'1234,5678,1137',但寫入數據庫'1234,5678'

當前日誌ID是[1234,5678]
新的日誌ID是[1234,5678,1137];使用骯髒的真正的新聞列表13寫入'1234,5678,1137'的log_id
SQL(2.0ms)UPDATE「news_lists」SET「log_ids」='1234,5678',「updated_at」='2012-01-02 02: 12:17.612283' WHERE( 「news_lists」 「ID」= 13)有關

的對象屬性是log_ids,其是含有另一種類型的對象的幾個ID的字符串。

所產生上面的輸出的源代碼:

def add_log(new_log) 
    new_ids = get_log_ids 
    Rails.logger.info("current log ids are #{new_ids}") 
    if new_ids.length >= NewsList.MAX_LENGTH 
    new_ids.shift 
    end 
    log_ids_will_change! 
    new_ids.push new_log.id 
    log_ids = new_ids.join "," 
    Rails.logger.info("new log ids are #{new_ids}; writing log_ids of '#{log_ids}' to NewsList #{id} with dirty #{changed?}") 
    save! 
end 
def get_log_ids 
    if log_ids 
    log_ids.split(",").map &:to_i 
    else 
    [] 
    end 
end 

任何人都可以提出什麼可能怎麼回事呢?

+0

如果是ActiveRecord,您是否需要通過自己訪問數據庫屬性,而不是因爲AR的工作原理而僅僅是「裸」變量? – 2012-01-02 02:38:54

回答

3

將自己添加到self.log_ids = new_ids.join ","否則,您將只分配給本地變量(同名)而不是db-persisted屬性(列)。

+0

哇。我以前從未遇到過ActiveRecord特別的怪癖。我不知道這兩種語法之間是否有任何區別,但是是的,它解決了這個問題。爲什麼它會創建一個同名的局部變量? – AlexC 2012-01-02 09:26:11

+0

當你賦值給setter時,你必須一直顯式地加上'self',否則解釋器會創建一個局部變量,它無法知道你是要創建一個局部變量還是調用setter,所以默認行爲是創建一個局部變量。對於getter是不同的,因爲如果它沒有在範圍中找到具有該名稱的本地var,它會嘗試調用該方法,因此對於getter我們不需要用self作爲前綴。 – clyfe 2012-01-02 10:54:12