2014-10-01 83 views
1

的Rails 4.0.4 4時更新類型,紅寶石2.1.2的Rails遷移到單表繼承

我想使用STI像這樣:

User < ActiveRecord::Base 
Admin < User 

但目前我有:

User < ActiveRecord::Base 
Info < ActiveRecord::Base 

所以我改變了我的模型,然後開始寫我的移植。在我的移民,我第一次添加一列,讓STI:

add_column :users, :type, :string 

然後我想目前更新數據庫中的用戶是管理員

# Place I'm currently stuck 

然後,我將我的所有信息記錄到用戶表

Info.all.each { |info| User.create(name: info.name, email: info.email) } 

除了將以前的用戶轉換爲管理員之外,一切似乎都奏效。這裏有一些事情我已經試過:

# Seems to work, but doesn't actually save type value 
User.each do |user| 
    user.becomes!(Admin) 
    user.save! # evaluates to true, doesn't have any errors 
end 

# Seems to work, but doesn't actually save type value 
# I've also tried a combo of this one and the above one 
User.each do |user| 
    user.type = "Admin" 
    user.save! # evaluates to true, doesn't have any errors 
end 

User.each do |user| 
    user = user.becomes!(Admin) 
    user.save! # evaluates to true, doesn't have any errors 
end 

# Seems to work, but doesn't actually save type value 
User.each do |user| 
    user.update_attributes(type: "Admin") 
end 

每次局部用戶變量似乎有正確的類型(「管理」),連同保存評估爲真,但是當我檢查Admin.count或檢查用戶輸入價值,它總是零。我知道你不應該改變它們,但這只是將數據遷移到STI,然後我就可以開始創建具有適當類的用戶或管理員。

至少我認爲Rails應該提出錯誤,設置錯誤或以某種方式讓開發人員知道它沒有保存調用。

+0

注意,在內存中的對象仍然是以前的類。嘗試重新加載對象,並且您應該在這些用戶上看到新的類。 – Nobita 2014-10-01 23:30:15

+0

我通過執行'User.where(...)'和'Admin.all'獲得與更新前相同的結果 – 2014-10-02 16:25:41

回答

1

如果你有更多的數據庫中行User.each會變得非常緩慢,因爲它使一個SQL調用每個用戶。

通常,您可以使用User.update_all(field: value)在一次SQL調用中完成此操作,但還有另一個原因可以避免這種情況:如果User型以後刪除,遷移將不再運行。更新一次所有行,而不引用模型

一種方法是使用在遷移原始SQL:

def up 
    execute "UPDATE users SET type = 'Admin' WHERE type IS NULL" 
end 
+0

肯定會認爲這比實例化所有這些對象要好得多 – 2015-08-01 14:59:46

3

事實證明,雖然update_attributes不適用於類型(我還沒有研究爲什麼),update_column確實工作。

所以遷移變得簡單:

User.each do |user| 
    user.update_columns(type: "Admin") 
end 

的原因,這個工程和其他更新不大概可以追溯到無論是回調或驗證沒有運行。我沒有回調會阻止它,但也許有默認的Rails藥粥type

http://apidock.com/rails/ActiveRecord/Persistence/update_columns