簡體   English   中英

在運行rake db:migrate時,創建遷移以向表添加列的Rails會導致錯誤

[英]Rails creating migration to add columns to table causes error when running rake db:migrate

我有一個名為“users”的模型,我創建了一個新的遷移,將一些列添加到users表中。 現在當我運行rake db:migrate時,我得到下面的錯誤b / c它試圖再次創建users表

$ 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

Rails在數據庫的“schema_migrations”表中跟蹤遷移。 除非存在“20120511224920”的條目,即Devise遷移,否則它將嘗試再次運行它,它似乎已經存在。

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

該錯誤表明它正在嘗試再次運行原始DeviseCreateUsers遷移,因為users表已經存在而無法運行。

要解決此問題,您可以運行DeviseCreateUsers的向下遷移,然后正常運行遷移。 你可以這樣做:

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

其中20121031XXXXXXXX是遷移名稱的日期戳。 換句話說,您將進行名為20120410214815_devise_create_users.rb的遷移,並從文件名中復制日期戳並將其粘貼到命令中。 這是關於遷移的Rails指南以供參考

編輯:這在評論中注明,但只是一個警告。 對表執行向下遷移將丟失表所具有的任何條目。 我假設你在開發模式下運行,所以這應該不是問題。 如果你正在制作中,你將需要采取額外的步驟來備份表數據並在之后重新加載它,否則你將會有糟糕的一天(或者可能是一周)。

您可以嘗試創建一個新的數據庫,然后再次遷移它:

rake db:drop:all
rake db:create:all
rake db:migrate

從我從中收集到的內容:

  • 您已擁有用戶模型
  • 你有一個生產版本
  • 你運行了默認的rails generate devise:install
  • 然后你運行rails generate devise User

我希望:

  • 您使用源代碼管理
  • 你經常檢查代碼

注意:如果沒有,您將了解為什么需要這樣做。

在生成Devise之前將代碼還原到

希望您可以在生成Devise之前創建一個新的沙箱。 如果沒有,請復制項目目錄並手動完成。 唯一的另一個選項是手動編輯Devise生成的所有文件。

重新運行你的Devise一代

  • 讀取gem'devise'到你的Gemfile
  • rails generate devise:install
  • rails生成設計模型

確保模型不存在! 如果你不這樣做,你會遇到你目前遇到的問題。

將當前用戶從一個模型遷移到另一個模型

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

編輯:您可能會找到一種方法來自定義Devise以使用您的算法。 這可能會更好,但更多的工作和相當脆弱。

另一件事是您的身份驗證模型不應該超載帳戶數據。 您應該有一個僅處理身份驗證的模型,該身份驗證具有存儲您可能要跟蹤帳戶的任何內容的帳戶數據模型。

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

請遵循語法..

  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.

像rake db:migrate:down VERSION =版本號#version number是您要遷移的版本。

我猜你有時會運行rails generate devise user generate DeviseCreateUsers rails generate devise user生成DeviseCreateUsers 如果已創建用戶模型和用戶表,則可以從db / migrate中刪除生成的遷移文件。

檢查可能為遷移版本提供意外值的一些環境變量。 我在Stack Overflow上發現了一個老問題 (並且如果它已經過時,請原諒我) db:migrate正在破壞表,而不是應用現有的新遷移。

他們最終發現環境變量導致db:migrate以版本參數“0”運行,這在功能上等同於rake db:migrate:down

是否可能由於意外更改版本以包含或匹配以前的遷移DeviseCreateUsers而導致您的情況?

你試一試

在第一個文件中

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

這將覆蓋任何其他表

根據您的說法,您使用此命令創建了新的遷移

$ rails生成遷移AddDetailsToUsers home_phone:decimal cell_phone:decimal work_phone:decimal birthday:date home_address:text work_address:text position:string company:string

我不確定它只是一個錯字但它應該是“AddDetailsToUser”而不是“用戶”。 再次檢查,我們將能夠幫助您。 這是用於設計生成的模型。 當你提到User時,在db中它會查找用戶。

Ruby on Rails遵循語言約定.table_name是Plural,但model_name是Singular。 您必須在您使用的命令中使用model_name。

如果要使用table_name,請使用此方法

rails g migration add_details_to_users home_phone:decimal ......等

如果您需要手動執行一些臟遷移:

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

A.new.migrate(:up)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM