2012-10-31 33 views
20

我創建了一個名爲「users」的模型,並且我創建了一個新的遷移,將一些列添加到users表中。現在,當我運行耙分貝:遷移,我得到下面的二/三它試圖創建用戶表再次創建遷移以添加列到表的Rails導致運行rake數據庫時出錯:遷移

$ rake db:migrate 
== DeviseCreateUsers: migrating ============================================== 
-- create_table(:users) 
rake aborted! 
An error has occurred, all later migrations canceled: 

Mysql::Error: Table 'users' already exists: CREATE TABLE `users`..... 

爲什麼嘗試重新創建表的錯誤?

這是我用來創建新的遷移

$ rails generate migration AddDetailsToUsers home_phone:decimal cell_phone:decimal work_phone:decimal birthday:date home_address:text work_address:text position:string company:string 

新的遷移看起來像這樣的命令:

class AddDetailsToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :home_phone, :decimal 
    add_column :users, :cell_phone, :decimal 
    add_column :users, :work_phone, :decimal 
    add_column :users, :birthday, :date 
    add_column :users, :home_address, :text 
    add_column :users, :work_address, :text 
    add_column :users, :position, :string 
    add_column :users, :company, :string 
    end 
end 

編輯

20120511224920_devise_create_users

class DeviseCreateUsers < ActiveRecord::Migration 
    def change 
    create_table(:users) do |t| 
     ## Database authenticatable 
     t.string :email,    :null => false, :default => "" 
     t.string :username,   :null => false, :default => "" 
     t.string :encrypted_password, :null => false, :default => "" 

     ## Recoverable 
     t.string :reset_password_token 
     t.datetime :reset_password_sent_at 

     ## Rememberable 
     t.datetime :remember_created_at 

     ## Trackable 
     t.integer :sign_in_count, :default => 0 
     t.datetime :current_sign_in_at 
     t.datetime :last_sign_in_at 
     t.string :current_sign_in_ip 
     t.string :last_sign_in_ip 

     ## Encryptable 
     # t.string :password_salt 

     ## Confirmable 
     # t.string :confirmation_token 
     # t.datetime :confirmed_at 
     # t.datetime :confirmation_sent_at 
     # t.string :unconfirmed_email # Only if using reconfirmable 

     ## Lockable 
     # t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts 
     # t.string :unlock_token # Only if unlock strategy is :email or :both 
     # t.datetime :locked_at 

     ## Token authenticatable 
     # t.string :authentication_token 


     t.timestamps 
    end 

    add_index :users, :email,    :unique => true 
    add_index :users, :reset_password_token, :unique => true 
    # add_index :users, :confirmation_token, :unique => true 
    # add_index :users, :unlock_token,   :unique => true 
    # add_index :users, :authentication_token, :unique => true 
    end 
end 

20120619023856_add_name_to_users

class AddNameToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :first_name, :string 
    add_column :users, :last_name, :string 
    end 
end 

20121031174720_add_details_to_users.rb

class AddDetailsToUsers < ActiveRecord::Migration 
    def change 
    add_column :users, :home_phone, :decimal 
    add_column :users, :cell_phone, :decimal 
    add_column :users, :work_phone, :decimal 
    add_column :users, :birthday, :date 
    add_column :users, :home_address, :text 
    add_column :users, :work_address, :text 
    add_column :users, :position, :string 
    add_column :users, :company, :string 
    end 
end 
+0

從輸出看起來好像在DeviseCreateUsers期間發生錯誤,而不是在您的新遷移中。您是否有另一個(舊的)遷移已經創建了Users表? – fwalch

+0

是的,我願意。但我認爲我應該能夠像我一樣添加新的遷移並運行rake數據庫:遷移應該只運行尚未運行的遷移。 – Catfish

+0

新遷移甚至沒有運行;好像你有另外兩個都試圖創建用戶表('DeviseCreateUsers'和一個較老的遷移)。你應該改變'DeviseCreateUsers'來使用'add_column's而不是試圖創建表。 – fwalch

回答

10

Rails的跟蹤的遷移在你的數據庫的「schema_migrations」表。除非有一個條目「20120511224920」,這是Devise遷移,它將嘗試再次運行它,它似乎已經存在。

如果是這種情況,可以手動添加到表格中。

+1

我沒有意識到這一點。我運行了一個rake db:reset,所以現在唯一的遷移是新的。如果我想知道schema_migrations表,我至少可以檢查一下。 – Catfish

+0

儘管我無法確定這是什麼問題,但我猜測schema_migrations表中缺少一條記錄。 – Catfish

6

錯誤是說,它試圖重新運行原有DeviseCreateUsers遷移,不能因爲用戶表已經存在。

要解決此問題,可以運行DeviseCreateUsers的向下遷移,然後像平常一樣運行遷移。您可以這樣做:

rake db:migrate:down VERSION=20121031XXXXXXXX 
rake db:migrate 

其中20121031XXXXXXXX是遷移名稱的日期標記。換句話說,您將進行名爲20120410214815_devise_create_users.rb的遷移,並從文件名複製日期戳並將其粘貼到命令中。 Here's the Rails Guide on Migrations for reference

編輯:這是在評論中註明,但只是一個警告的話。對錶執行向下遷移將失去表所具有的任何條目。我假設你在開發模式下運行,所以這應該不成問題。如果你在製作,你需要採取額外的步驟來備份表格數據並在之後重新載入,否則你將會有糟糕的一天(或者一週)。

+0

如果我運行向下遷移雖然,這將刪除我的表和所有的數據在那裏是正確的?根據你發佈的指南,我應該能夠添加一個新的遷移並運行rake數據庫:migrate應該能夠判斷是否有任何遷移已經運行,而不是這次運行那些遷移。 – Catfish

+1

你說得對。我假定你在開發模式下運行,重新創建用戶表是可以接受的。 Rails應該能夠告訴你已經運行的是什麼遷移。我剛剛讀了其他答案的評論。你有兩個運行'create_table:users'的遷移嗎? – GorrillaMcD

1

我想你跑rails generate devise user某時產生DeviseCreateUsers。如果您已創建用戶模型和用戶表,則可以從db/migrate中刪除生成的遷移文件。

+0

但是,如果我刪除生成的遷移,當我移到生產並在新數據庫上運行遷移時,我將缺少一些遷移。 – Catfish

+0

我認爲你已經有了用於創建用戶表的另一個遷移。 – Yanhao

+0

我確實有用於創建用戶表的另一個遷移。 – Catfish

4

你可以嘗試做一個新的數據庫,然後再進行遷移:

rake db:drop:all 
rake db:create:all 
rake db:migrate 
+0

我做了一個rake db:reset,然後運行rake:db:migrate,但是這仍然不能解釋爲什麼我不能創建一個新的遷移並運行它。 Rails通常可以很好地處理這個問題。 – Catfish

2

所以從我從這個雲集:

  • 您已經有了一個User模型
  • 您有一個版本的這個生產
  • 你跑了默認的軌道產生色器件:安裝
  • 然後您運行rails generate devise用戶

我希望:

  • 您使用源代碼控制
  • 您在很多

注意檢查代碼:如果不是,你要學習,爲什麼你需要這樣做。

還原你的代碼,您生成設計

希望,你可以生成設計之前創建的點右邊一個新的沙箱前。如果沒有,請複製您的項目目錄並手動完成。唯一的其他選擇是手動編輯Devise生成的所有文件。

重新運行設計一代

  • READD寶石 '設計' 到您的Gemfile
  • 軌產生色器件:安裝
  • 軌生成設計模型

確保模型做不存在!如果你沒有解決你目前遇到的問題。

從一個模型遷移當前用戶對其他

如果你可以生成一個腳本,完全從舊用戶模式轉變的認證信息,以新的,對你有好處。如果您使用Devise的另一種哈希算法進行當前身份驗證,那麼您將要麼使其所有密碼無效,並要求您的用戶使用其電子郵件中的確認碼創建新密碼,或者可以在用戶登錄時遷移它們第一種方法是乾淨的,完整的,粗魯的。第二種方法是醜陋,不完整和沉默。選擇你喜歡的方法。

編輯:你也許可以找到一種方法來定製Devise來代替使用你的算法。這可能會更好,但更多的工作和相當脆弱。

另一件事是您的驗證模型不應該與帳戶數據過載。您應該有一個只處理驗證的模型,has_a帳戶數據模型存儲您可能想要跟蹤的帳戶的任何內容。

+0

幸運的是,我現在還沒有生產,所以我最終只是刪除了我的數據庫數據,但我只是想知道什麼會導致create_table腳本嘗試再次運行,而不是正確跳過它並運行新的使用add_columns遷移 – Catfish

+0

哦,那麼你不需要遷移用戶,但我仍然可以從帳戶數據中分離認證數據。至於正確性,Rails假設你想在遷移中做所有事情。要將用戶用作身份驗證模型,您需要在運行「rails generate devise model」命令之前從數據庫中刪除舊的。 –

0

只是嘗試

在第一個文件

create_table(:users), :force => true do |t| 

這將覆蓋任何其他表

+0

但這會覆蓋我的表是否正確?正如你可以從所有其他評論中看到的那樣,我試圖將列添加到數據庫中,而不必刪除數據。 Rails能夠處理這個問題。 – Catfish

2

使用上下方法。這對回滾和運行特定的遷移文件很有用。

請遵循語法..

class AddDetailsToUsers < ActiveRecord::Migration 
    def self.up 
     add_column :users, :home_phone, :decimal 
     add_column :users, :cell_phone, :decimal 
     add_column :users, :work_phone, :decimal 
     add_column :users, :birthday, :date 
     add_column :users, :home_address, :text 
     add_column :users, :work_address, :text 
     add_column :users, :position, :string 
     add_column :users, :company, :string 
    end 

    def self.down 
     remove_column :users, :home_phone 
     remove_column :users, :cell_phone 
     remove_column :users, :work_phone 
     remove_column :users, :birthday 
     remove_column :users, :home_address 
     remove_column :users, :work_address 
     remove_column :users, :position 
     remove_column :users, :company 
    end 
    end 


    In this case please try to migrate using version number. 

像耙分貝:遷移:縮小版本=版本號的#Version號是你要遷移的版本。

+0

爲什麼沒有創建一個類似這樣的'rails生成遷移AddDetailsToUsers ....'的遷移時創建的向上和向下方法.... – Catfish

+0

嗨。向上和向下方法將在rails 2.2.2中生成。 – vijikumar

+1

Rails 3.1通過提供新的更改方法使遷移變得更加智能。此方法對於編寫建設性遷移(添加列或表)是首選。遷移知道如何遷移數據庫並在遷移回滾時將其反轉,而無需編寫單獨的停用方法。 所以看起來你不用擔心def self.down,因爲Rails現在足夠聰明,知道如何回滾它。 – vijikumar

1

檢查可能爲遷移版本提供意外值的一些環境變量。我發現堆棧溢出an old question(並原諒我,如果它是過時的)其中db:migrate破壞表,而不是應用現有的新遷移。

他們最終發現,一個環境變量是造成db:migrate用的「0」的版本參數是功能上等同於rake db:migrate:down

運行是有可能,你的情況可以通過版本而造成意外地改變包括或匹配以前的移民DeviseCreateUsers

+0

我不這麼認爲,因爲所有的遷移對它們都有不同的時間戳 – Catfish

0

根據你說你用這個命令來創建一個新的遷移

$軌產生遷移AddDetailsToUsers HOME_PHONE:小數cell_phone:小數work_phone:小數生日:日期home_address:文本work_address:文本位置:串公司:字符串

林不知道它只是一個錯字,但它應該是「AddDetailsToUser」而不是「用戶」。只需再次檢查,我們將能夠爲您提供幫助。這是爲設計生成的模型。當你提到用戶,在分貝它尋找用戶。

Ruby on Rails遵循語言約定。表名是複數,但model_name是單數。您必須在您使用的命令中使用model_name。

如果你想使用表名,然後使用這個

軌摹遷移add_details_to_users HOME_PHONE:小數......等

0

如果你需要手動做一些骯髒的遷移:

class A < ActiveRecord::Migration 
    def up 
    add_column :images, :name 
    end 
end 

A.new.migrate(:up) 
相關問題