2014-09-03 54 views
0

我的數據模型中有一些STI。 Task記錄有兩種類型:PrimaryTaskSecondaryTask。所以我的ActiveRecord的模式是這樣的:ActiveRecord#becomes!記錄不存儲

class Task < ActiveRecord::Base 
end 

class PrimaryTask < Task 
    has_many :secondary_tasks 
end 

class SecondaryTask < Task 
    belongs_to :primary_task 
end 

我想提供一個方法來「促進」一SecondaryTaskPrimaryTask永久(如,持久化到數據庫)。從仔細閱讀文檔,看起來像the #becomes! method是我想要的,但我無法得到它來保存數據庫中的更改。

id = 1 
secondary_task = SecondaryTask.find(id) 
primary_task = secondary_task.becomes!(PrimaryTask) 

primary_task.id   # => 1 
primary_task.class  # => PrimaryTask 
primary_task.type  # => "PrimaryTask" 
primary_task.new_record? # => false 
primary_task.changes  # => { "type"=>[nil,"PrimaryTask"] } 

primary_task.save!  # => true 
primary_task.reload  # => raises ActiveRecord::RecordNotFound: Couldn't find PrimaryTask with id=1 [WHERE "tasks"."type" IN ('PrimaryTask')] 

# Note: secondary_task.reload works fine, because the task's type did not change in the DB 

不知道怎麼回事?我嘗試了以下的東西,無濟於事。我誤解了becomes!

  • 隊的戰績是萬一「髒」的save!電話是一個空操作,因爲沒有任何屬性被標記髒(primary_task.update_attributes(updated_at: Time.current) - 沒有幫助)
  • 的情況下,實際上破壞secondary_task他們都有相同的id是一個問題。沒有幫助。該SecondaryTask記錄已被刪除,但沒有PrimaryTask創建(儘管調用save!返回true

更新1

該日誌顯示可能的問題:

UPDATE "tasks" SET "type" = $1 WHERE "tasks"."type" IN ('PrimaryTask') AND "tasks"."id" = 2 [["type", "PrimaryTask"]] 

所以更新失敗,因爲WHERE子句導致找不到記錄。

+1

正顯示出一些日誌? – Aguardientico 2014-09-03 23:32:32

+0

啊哈!好問題,甚至沒有想到在那裏看。更新問題... – 2014-09-03 23:40:36

+0

您是否嘗試過使用'#成爲'而不是'#becomes!'? – Aguardientico 2014-09-04 00:16:49

回答

0

想通了。結果發現在ActiveRecord版本4.0.0中有一個錯誤。 It has since been patched。引入此修補程序的關鍵是在兩個實例中正確設置changes。因此,現在您可以在原始實例上調用save(在我的示例中爲secondary_task),它將更改數據庫中的類型。請注意,在新實例上調用save(對於我來說primary_task)將不保存更改,因爲問題中描述的行爲:它將在SQL UPDATE調用中包含WHERE子句,這將導致記錄找不到,因此該呼叫什麼都不做。

下面是用ActiveRecord什麼工作> 4.1.0:

id = 1 
secondary_task = SecondaryTask.find(id) 
primary_task = secondary_task.becomes!(PrimaryTask) 

secondary_task.changes # => { "type"=>["SecondaryTask","PrimaryTask"] } 
primary_task.changes # => { "type"=>["SecondaryTask","PrimaryTask"] } 

secondary_task.save! # => true 

primary_task.reload # => works because the record was updated as expected 
secondary_task.reload # => raises ActiveRecord::RecordNotFound, as expected