Làm cách nào để đổi tên cột cơ sở dữ liệu trong di chuyển Ruby on Rails?


Câu trả lời:


2308
rename_column :table, :old_column, :new_column

Có lẽ bạn sẽ muốn tạo một di chuyển riêng để làm điều này. (Đổi tên FixColumnNamenhư bạn muốn.):

script/generate migration FixColumnName
# creates  db/migrate/xxxxxxxxxx_fix_column_name.rb

Sau đó chỉnh sửa di chuyển để làm theo ý của bạn:

# db/migrate/xxxxxxxxxx_fix_column_name.rb
class FixColumnName < ActiveRecord::Migration
  def self.up
    rename_column :table_name, :old_column, :new_column
  end

  def self.down
    # rename back if you need or do something else or do nothing
  end
end

Đối với Rails 3.1 sử dụng:

Mặc dù, updowncác phương thức vẫn được áp dụng, Rails 3.1 nhận được một changephương thức "biết cách di chuyển cơ sở dữ liệu của bạn và đảo ngược nó khi di chuyển được khôi phục mà không cần phải viết một phương thức riêng biệt".

Xem " Di chuyển bản ghi hoạt động " để biết thêm thông tin.

rails g migration FixColumnName

class FixColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

Nếu bạn tình cờ có một loạt các cột để đổi tên hoặc một cái gì đó sẽ phải lặp đi lặp lại tên bảng nhiều lần:

rename_column :table_name, :old_column1, :new_column1
rename_column :table_name, :old_column2, :new_column2
...

Bạn có thể sử dụng change_tableđể giữ mọi thứ gọn gàng hơn:

class FixColumnNames < ActiveRecord::Migration
  def change
    change_table :table_name do |t|
      t.rename :old_column1, :new_column1
      t.rename :old_column2, :new_column2
      ...
    end
  end
end

Sau đó, db:migratenhư thường lệ hoặc tuy nhiên bạn đi về doanh nghiệp của bạn.


Đối với đường ray 4:

Trong khi tạo một Migrationđể đổi tên một cột, Rails 4 tạo ra một changephương thức thay vì updownnhư đã đề cập trong phần trên. changePhương thức được tạo là:

$ > rails g migration ChangeColumnName

sẽ tạo một tệp di chuyển tương tự như:

class ChangeColumnName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

24
self.down phải luôn luôn trái ngược với self.up, vì vậy "nếu bạn cần hoặc làm gì khác hoặc không làm gì" thì không thực sự được khuyến khích. Chỉ cần làm: rename_column: table_name ,: new_column ,: old_column
Luke Griffiths

3
Mặc dù đó là cách làm thông thường để hoàn nguyên những gì bạn đã làm trong self.uptôi sẽ không nói self.down"nên luôn luôn ngược lại". Trong tùy thuộc vào bối cảnh di chuyển của bạn. Chỉ cần đặt "đối diện" có thể không phải là "di chuyển" xuống.
ngay bây giờ

23
Trong Rails 3.1, bạn có thể thay thế def self.updef self.downbằng def changevà nó sẽ biết cách khôi phục.
Turadg

2
Turadg - * nó sẽ biết cách quay ngược lại hầu hết thời gian. Tôi thấy changephương pháp này không đầy đủ bằng chứng, vì vậy có xu hướng sử dụng updownphương pháp cho việc di chuyển phức tạp.
JellyFishBoy

6
Có đổi tên loại bỏ chỉ mục?
Sung Cho

68

Theo tôi, trong trường hợp này, tốt hơn là sử dụng rake db:rollback, sau đó chỉnh sửa di chuyển của bạn và chạy lại rake db:migrate.

Tuy nhiên, nếu bạn có dữ liệu trong cột mà bạn không muốn mất thì hãy sử dụng rename_column.


34
Ngay cả trong một "nhóm một", nếu bạn có nhiều phiên bản ứng dụng của bạn đang chạy, giả sử trong các môi trường khác nhau hoặc trên nhiều máy tính, v.v., quản lý di chuyển đã chỉnh sửa là một nỗi đau lớn. Tôi chỉ chỉnh sửa di chuyển nếu tôi vừa tạo và nhận ra nó sai và chưa chạy nó theo nghĩa đen ở bất kỳ nơi nào khác.
Yetanotherjosh

1
Tôi đã phải khởi động lại máy chủ sau đó.
Muhammad Hewedy

7
Kỹ thuật này chỉ nên được sử dụng trong trường hợp các thay đổi của bạn chưa được hợp nhất với nhánh sản xuất của bạn và các thay đổi khác không phụ thuộc vào tính bền vững của dữ liệu. Trong hầu hết mọi hoàn cảnh sản xuất, đây KHÔNG phải là phương pháp ưa thích.
Collin Graves

4
không bao giờ làm điều này
new2cpp

4
Tôi muốn nói với nhóm của mình: 'Di chuyển là miễn phí' Chi phí chỉnh sửa di chuyển đã được phát hành tự nhiên rất cao: Tôi đã dành vài giờ để tìm hiểu lý do tại sao mã của tôi không hoạt động trước khi tôi nhận ra một thành viên khác trong nhóm đã quay lại và chỉnh sửa một di chuyển mà tôi đã chạy. Vì vậy, đừng chỉnh sửa di chuyển hiện có, hãy sử dụng một di chuyển mới để thay đổi lược đồ, bởi vì ... ... 'Di chuyển là miễn phí!' (điều đó không hoàn toàn đúng, nhưng nó có ý nghĩa)
TerryS

31

Nếu cột đã được điền dữ liệu và sống trong sản xuất, tôi khuyên bạn nên thực hiện từng bước một để tránh thời gian ngừng sản xuất trong khi chờ di chuyển.

Trước tiên tôi sẽ tạo một di chuyển db để thêm các cột có (các) tên mới và điền chúng với các giá trị từ tên cột cũ.

class AddCorrectColumnNames < ActiveRecord::Migration
  def up
    add_column :table, :correct_name_column_one, :string
    add_column :table, :correct_name_column_two, :string

    puts 'Updating correctly named columns'
    execute "UPDATE table_name SET correct_name_column_one = old_name_column_one, correct_name_column_two = old_name_column_two"
    end
  end

  def down
    remove_column :table, :correct_name_column_one
    remove_column :table, :correct_name_column_two
  end
end

Sau đó, tôi cam kết thay đổi đó và đẩy sự thay đổi vào sản xuất.

git commit -m 'adding columns with correct name'

Sau đó, một khi cam kết đã được đưa vào sản xuất, tôi sẽ chạy.

Production $ bundle exec rake db:migrate

Sau đó, tôi sẽ cập nhật tất cả các chế độ xem / bộ điều khiển đã tham chiếu tên cột cũ thành tên cột mới. Chạy qua bộ thử nghiệm của tôi và cam kết chỉ những thay đổi đó. (Sau khi chắc chắn rằng nó hoạt động tại địa phương và vượt qua tất cả các bài kiểm tra trước!)

git commit -m 'using correct column name instead of old stinky bad column name'

Sau đó, tôi sẽ thúc đẩy cam kết sản xuất.

Tại thời điểm này, bạn có thể xóa cột ban đầu mà không phải lo lắng về bất kỳ loại thời gian chết nào liên quan đến việc di chuyển.

class RemoveBadColumnNames < ActiveRecord::Migration
  def up
    remove_column :table, :old_name_column_one
    remove_column :table, :old_name_column_two
  end

  def down
    add_column :table, :old_name_column_one, :string
    add_column :table, :old_name_column_two, :string
  end
end

Sau đó đẩy di chuyển mới nhất này vào sản xuất và chạy bundle exec rake db:migratetrong nền.

Tôi nhận ra rằng đây là một quá trình liên quan nhiều hơn một chút, nhưng tôi muốn làm điều này hơn là có vấn đề với việc di chuyển sản xuất của tôi.


2
Tôi thích suy nghĩ đằng sau điều này, và tôi sẽ +1 lần lặp lại của bạn nhưng việc cập nhật dữ liệu đó sẽ mất rất nhiều thời gian để thực hiện vì nó đi qua đường ray và thực hiện từng hàng một. Việc di chuyển sẽ thực thi nhanh hơn nhiều với các câu lệnh sql thô để cập nhật các cột được đặt tên chính xác. Ví dụ: trong tập lệnh di chuyển db đầu tiên, sau khi thêm các tên cột trùng lặp, execute "Update table_name set correct_name_column_one = old_name_column_one"
Gui Weinmann

1
@ mr.ruh.roh ^ Hoàn toàn đồng ý, nên đã viết nó ngay từ đầu. Tôi đã chỉnh sửa để phản ánh một tuyên bố sql hiệu quả duy nhất. Cảm ơn đã kiểm tra vệ sinh.
Paul Pettengill

2
Điều gì xảy ra với các mục ở giữa việc chuyển sang bảng mới và cập nhật mã để sử dụng bảng mới? Bạn có thể không có dữ liệu không có khả năng còn sót lại?
Stefan Dorunga

1
trong khi đây là câu trả lời 'an toàn', tôi cảm thấy nó không đầy đủ. Nhiều người ở đây nói không làm điều này - tại sao? sự kiên trì của dữ liệu. Và đó là hợp lệ. Có lẽ cách ít đau đớn nhất để hoàn thành mục tiêu là tạo ra các trường mới, điền chúng vào dữ liệu từ các cột cũ, điều chỉnh bộ điều khiển. Nếu bạn muốn xóa các cột cũ, chắc chắn bạn sẽ phải chỉnh sửa các khung nhìn. Chi phí để giữ chúng là không gian db thêm và một số nỗ lực trùng lặp trong bộ điều khiển. Sự đánh đổi là rất rõ ràng.
Jerome


18

Chạy lệnh dưới đây để tạo tệp di chuyển:

rails g migration ChangeHasedPasswordToHashedPassword

Sau đó, trong tệp được tạo trong db/migratethư mục, viết rename_columnnhư dưới đây:

class ChangeOldCoulmnToNewColumn < ActiveRecord::Migration
  def change
     rename_column :table_name, :hased_password, :hashed_password
  end
end

14

Từ API:

rename_column(table_name, column_name, new_column_name)

Nó đổi tên một cột nhưng vẫn giữ nguyên kiểu và nội dung.


12

Một số phiên bản của Ruby on Rails hỗ trợ phương pháp lên / xuống để di chuyển và nếu bạn có phương pháp lên / xuống trong quá trình di chuyển của mình thì:

def up
    rename_column :table_name, :column_old_name, :column_new_name
end

def down
    rename_column :table_name, :column_new_name, :column_old_name
end

Nếu bạn có changephương thức trong di chuyển của mình, thì:

def change
    rename_column :table_name, :column_old_name, :column_new_name
end

Để biết thêm thông tin, bạn có thể di chuyển: Ruby on Rails - Di chuyển hoặc Di chuyển bản ghi hoạt động .


11

Nếu mã của bạn không được chia sẻ với mã khác, thì tùy chọn tốt nhất là chỉ cần rake db:rollback chỉnh sửa tên cột của bạn khi di chuyển vàrake db:migrate . Đó là nó

Và bạn có thể viết một di chuyển khác để đổi tên cột

 def change
    rename_column :table_name, :old_name, :new_name
  end

Đó là nó.


rake db:rollbacklà một gợi ý tuyệt vời. Nhưng như bạn đã nói, chỉ khi di chuyển chưa được đẩy.
danielricecodes

9

Là một lựa chọn thay thế, nếu bạn chưa kết hôn với ý tưởng di chuyển, có một viên ngọc hấp dẫn cho ActiveRecord sẽ tự động xử lý các thay đổi tên cho bạn, theo kiểu Datamapper. Tất cả những gì bạn làm là thay đổi tên cột trong mô hình của bạn (và đảm bảo bạn đặt Model.auto_upTHER! Ở cuối mô hình của bạn.rb) và viola! Cơ sở dữ liệu được cập nhật nhanh chóng.

https://github.com/DAddYE/mini_record

Lưu ý: Bạn sẽ cần nuke db / lược đồ.rb để ngăn xung đột

Vẫn trong giai đoạn beta và rõ ràng không dành cho tất cả mọi người nhưng vẫn là một lựa chọn hấp dẫn (tôi hiện đang sử dụng nó trong hai ứng dụng sản xuất không tầm thường mà không có vấn đề gì)


8

Nếu bạn cần chuyển đổi tên cột, bạn sẽ cần tạo một trình giữ chỗ để tránh lỗi tên cột trùng lặp . Đây là một ví dụ:

class SwitchColumns < ActiveRecord::Migration
  def change
    rename_column :column_name, :x, :holder
    rename_column :column_name, :y, :x
    rename_column :column_name, :holder, :y
  end
end

7

Nếu dữ liệu hiện tại không quan trọng đối với bạn, bạn có thể gỡ bỏ di chuyển ban đầu của mình bằng cách sử dụng:

rake db:migrate:down VERSION='YOUR MIGRATION FILE VERSION HERE'

Nếu không có dấu ngoặc kép, sau đó thực hiện thay đổi trong di chuyển ban đầu và chạy lại di chuyển lên bằng cách:

rake db:migrate

6

Chỉ cần tạo một di chuyển mới và trong một khối, sử dụng rename_columnnhư dưới đây.

rename_column :your_table_name, :hased_password, :hashed_password

6

Dành cho Ruby trên Rails 4:

def change
    rename_column :table_name, :column_name_old, :column_name_new
end

5

Thủ công chúng ta có thể sử dụng phương pháp dưới đây:

Chúng tôi có thể chỉnh sửa di chuyển theo cách thủ công như:

  • Mở app/db/migrate/xxxxxxxxx_migration_file.rb

  • Cập nhật hased_passwordlênhashed_password

  • Chạy lệnh dưới đây

    $> rake db:migrate:down VERSION=xxxxxxxxx

Sau đó, nó sẽ xóa di chuyển của bạn:

$> rake db:migrate:up VERSION=xxxxxxxxx

Nó sẽ thêm di chuyển của bạn với sự thay đổi được cập nhật.


nó sẽ không an toàn vì bạn có thể mất dữ liệu - nếu cột đã hoạt động. nhưng có thể làm cho cột và / hoặc bảng mới.
Tejas Patel

5

Tạo tệp di chuyển:

rails g migration FixName

# Tạo db / di chuyển / xxxxxxxxxx.rb

Chỉnh sửa di chuyển để làm theo ý của bạn.

class FixName < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

5

Chạy rails g migration ChangesNameInUsers (hoặc bất cứ điều gì bạn muốn đặt tên cho nó)

Mở tệp di chuyển vừa được tạo và thêm dòng này vào phương thức (ở giữa def changeend):

rename_column :table_name, :the_name_you_want_to_change, :the_new_name

Lưu tệp và chạy rake db:migratetrong bảng điều khiển

Kiểm tra của bạn schema.dbđể xem tên đã thực sự thay đổi trong cơ sở dữ liệu!

Hi vọng điêu nay co ich :)


5

Hãy KISS . Tất cả chỉ mất ba bước đơn giản. Các công việc sau đây cho Rails 5.2 .

1. Tạo một di chuyển

  • rails g migration RenameNameToFullNameInStudents

  • rails g RenameOldFieldToNewFieldInTableName- theo cách đó nó hoàn toàn rõ ràng đối với những người duy trì cơ sở mã sau này. (sử dụng số nhiều cho tên bảng).

2. Chỉnh sửa di chuyển

# I prefer to explicitly write thelên andxuốngmethods.

# ./db/migrate/20190114045137_rename_name_to_full_name_in_students.rb

class RenameNameToFullNameInStudents < ActiveRecord::Migration[5.2]
  def up
    # rename_column :table_name, :old_column, :new_column
    rename_column :students, :name, :full_name
  end

  def down
            # Note that the columns are reversed
    rename_column :students, :full_name, :name
  end
end

3. Chạy di chuyển của bạn

rake db:migrate

Và bạn đang đi đến các cuộc đua!


4
$:  rails g migration RenameHashedPasswordColumn
invoke  active_record
      create    db/migrate/20160323054656_rename_hashed_password_column.rb

Mở tệp di chuyển đó và sửa đổi tệp đó như dưới đây (Không nhập bản gốc của bạn table_name)

class  RenameHashedPasswordColumn < ActiveRecord::Migration
  def change
    rename_column :table_name, :hased_password, :hashed_password
  end
end

4
 def change
    rename_column :table_name, :old_column_name, :new_column_name
  end

3

Tạo một di chuyển Ruby on Rails :

$:> rails g migration Fixcolumnname

Chèn mã vào tệp di chuyển (XXXXXfixcolumnname.rb) :

class Fixcolumnname < ActiveRecord::Migration
  def change
    rename_column :table_name, :old_column, :new_column
  end
end

2

Mở bảng điều khiển Ruby on Rails của bạn và nhập:

ActiveRecord::Migration.rename_column :tablename, :old_column, :new_column

2

Bạn có hai cách để làm điều này:

  1. Trong loại này, nó tự động chạy mã ngược của nó, khi rollback.

    def change
      rename_column :table_name, :old_column_name, :new_column_name
    end
  2. Với kiểu này, nó chạy phương thức up khi rake db:migratevà chạy phương thức down khi rake db:rollback:

    def self.up
      rename_column :table_name, :old_column_name, :new_column_name
    end
    
    def self.down
      rename_column :table_name,:new_column_name,:old_column_name
    end

2

Tôi đang trên đường ray 5.2 và đang cố đổi tên một cột trên Người dùng đã nghĩ ra.

các rename_columnchút làm việc cho tôi, nhưng số ít :table_nameném một "bảng Người dùng không tìm thấy" lỗi. Số nhiều làm việc cho tôi.

rails g RenameAgentinUser

Sau đó thay đổi tệp di chuyển sang đây:

rename_column :users, :agent?, :agent

Ở đâu: đại lý? là tên cột cũ.


0

Cập nhật - Một người anh em họ thân của create_table là change_table, được sử dụng để thay đổi các bảng hiện có. Nó được sử dụng theo cách tương tự với created_table nhưng đối tượng mang lại cho khối biết nhiều thủ thuật hơn. Ví dụ:

class ChangeBadColumnNames < ActiveRecord::Migration
  def change
    change_table :your_table_name do |t|
      t.rename :old_column_name, :new_column_name
    end
  end
end

Cách này hiệu quả hơn nếu chúng ta thực hiện với các phương thức thay đổi khác, chẳng hạn như: remove / add index / remove index / add cột, ví dụ: chúng ta có thể làm thêm như:

# Rename
t.rename :old_column_name, :new_column_name
# Add column
t.string :new_column
# Remove column
t.remove :removing_column
# Index column
t.index :indexing_column
#...

0

Chỉ cần tạo di chuyển bằng lệnh

rails g migration rename_hased_password

Sau đó chỉnh sửa di chuyển thêm dòng sau trong phương thức thay đổi

rename_column :table, :hased_password, :hashed_password

Cái này cần phải dùng mẹo.


0

Rails 5 thay đổi di chuyển

ví dụ:

rails g model Student student_name: chuỗi age: số nguyên

nếu bạn muốn thay đổi cột student_name thành tên

Lưu ý: - nếu bạn không chạy rails db: di chuyển

Bạn có thể làm các bước sau

rails d model Student student_name: chuỗi age: số nguyên

Điều này sẽ xóa tệp di chuyển được tạo, Bây giờ bạn có thể sửa tên cột của mình

rails g model Tên sinh viên: chuỗi tuổi: số nguyên

Nếu bạn đã di chuyển (rails db: di chuyển), các tùy chọn sau để thay đổi tên cột

rails g di chuyển RemoveStudentNameFromStudent student_name: chuỗi

rails g di chuyển Tên AddNameToStudent: chuỗi


Không phải là: rails g migration RemoveStudentNameFromStudentS student_name:string(các sinh viên là số nhiều)?
BKSpurgeon

Ngoài ra, điều này là nguy hiểm: cột không được đổi tên, nhưng hoàn toàn bị loại bỏ và sau đó được gắn lại. Điều gì sẽ xảy ra với dữ liệu? Đây có thể không phải là những gì người dùng sẽ muốn.
BKSpurgeon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.