Đổi tên bảng trong đường ray


154

Tôi muốn đổi tên một bảng ... (bất kỳ bảng nào.)

Tôi đã thử dòng mã này:

ActiveRecord::ConnectionAdapters::SchemaStatements.rename_table(old_name, new_name)

Đây là điều kỳ lạ. Tôi biết tôi đã làm cho nó hoạt động lần đầu tiên, nhưng bây giờ tôi gặp lỗi này: phương thức không xác định 'rename_table' cho ActiveRecord :: ConnectionAd chương :: SchemaStatements: Module

Có thứ gì tôi cần đặt không?

Câu trả lời:


248

Bạn thường sẽ làm điều này trong một di chuyển:

class RenameFoo < ActiveRecord::Migration
  def self.up
    rename_table :foo, :bar
  end

  def self.down
    rename_table :bar, :foo
  end
end

1
Cảm ơn đã làm việc! Tôi vẫn còn bối rối tại sao dòng trước đó không. Ồ tốt ..
Tommy

@ Mẹ ơi, rename_tablephương thức được định nghĩa trong ActiveRecord::ConnectionAdapters::SchemaStatements. Nó có nghĩa là được trộn lẫn vào các mô-đun khác. Nếu bạn muốn chạy nó trực tiếp, tôi nghĩ bạn có thể làm đượcinclude ActiveRecord::ConnectionAdapters::SchemaStatements; rename_table :foo, :bar
cam

hoặc bạn có thể sử dụng ActiveRecord :: Migration.rename_table (: foo ,: bar) nếu bạn đã quá nghiêng. Nhưng di cư hoạt động tốt nhất. Bạn cũng muốn thay đổi tên của mô hình hoặc muốn giữ lại tên mô hình như cũ? Nếu vậy, bạn có thể muốn chỉ định tên bảng trong mô hình ActiveRecord bằng cách sử dụng "set_table_name: bar".
Aditya Sanghi

1
Bạn cũng có thể sử dụng biểu mẫu mới để di chuyển bằng phương pháp 'thay đổi' thay vì lên & xuống. ví dụ
MegaTux

def thay đổi, không def self.up / def.elf.down trong triển khai Rails hiện đại. Làm sau sẽ thất bại âm thầm.
huertanix

294

Hãy nhớ rằng trong Rails> = 3.1 bạn có thể sử dụng changephương thức.

 class RenameOldTableToNewTable < ActiveRecord::Migration
   def change
     rename_table :old_table_name, :new_table_name
   end 
 end

37
Điều này cũng sẽ di chuyển bất kỳ chỉ mục nào từ :old_table_nameđến:new_table_name
Gavin Miller

7
Chỉ cần một nhận xét nhỏ: Có lẽ thay đổi thành: old_named_things ,: new_named_things để nhắc nhở mọi người rằng tên bảng trong Activerecord thường được chia số nhiều.
Carpela

24

.rename_tablelà một phương thức cá thể, không phải là một phương thức lớp, vì vậy việc gọi Class.methodsẽ không hiệu quả. Thay vào đó, bạn sẽ phải tạo một thể hiện của lớp và gọi phương thức trên thể hiện, như thế này : Class.new.method.

[EDIT] Trong trường hợp này, ActiveRecord::ConnectionAdapters::SchemaStatements thậm chí không phải là một lớp (như được chỉ ra bởi cam), điều đó có nghĩa là bạn thậm chí không thể tạo một thể hiện của nó theo như những gì tôi đã nói ở trên. Và ngay cả khi bạn đã sử dụng ví dụ của cam class Foo; include ActiveRecord::ConnectionAdapters::SchemaStatements; def bar; rename_table; end; end;, nó vẫn không hoạt động như rename_tablemột ngoại lệ.

Mặt khác, ActiveRecord::ConnectionAdapters::MysqlAdapter một lớp và có khả năng lớp này bạn phải sử dụng để đổi tên bảng của mình (hoặc SQLite hoặc PostgreQuery, tùy thuộc vào cơ sở dữ liệu nào bạn đang sử dụng). Bây giờ, như nó xảy ra, ActiveRecord::ConnectionAdapters::MysqlAdapterđã có thể truy cập thông qua Model.connection, vì vậy bạn sẽ hoàn toàn có thể làm được Model.connection.rename_table, sử dụng bất kỳ mô hình nào trong ứng dụng của bạn. [/BIÊN TẬP]

Tuy nhiên, nếu bạn muốn đổi tên vĩnh viễn một bảng, tôi sẽ đề nghị sử dụng di chuyển để thực hiện. Thật dễ dàng và là cách ưa thích để thao tác cấu trúc cơ sở dữ liệu của bạn với Rails. Đây là cách thực hiện:

# Commandline
rails generate migration rename_my_table

# In db/migrate/[timestamp]_rename_my_table.rb:
class RenameMyTable < ActiveRecord::Migration
  def self.up
    rename_table :my_table, :my_new_table
  end

  def self.down
    rename_table :my_new_table, :my_table
  end
end

Sau đó, bạn có thể chạy di chuyển của mình với rake db:migrate(gọi self.upphương thức) và sử dụng rake db:rollback(gọi self.down) để hoàn tác di chuyển.


Tôi đồng ý rằng đó rename_tablelà một phương thức cá thể, nhưng nó không được xác định trong một lớp, do đó, đề xuất gọi của Class.new.methodbạn sẽ không hoạt động (ví dụ: ActiveRecord::ConnectionAdapters::SchemaStatements.newđưa ra lỗi oMethodError: undefined method mới 'cho ActiveRecord :: ConnectionAd chương :: SchemaStatements: Module`
cam

1
Cũng đáng chỉ ra rằng, nếu bạn có một mô hình được liên kết với bảng bạn đang đổi tên, đang chạy rake db:migratehoặc rake db:rollbacksẽ không đổi tên tệp model.rb. Bạn sẽ cần phải thay đổi thủ công tệp model.rb.
9monkey

1
Trong các phiên bản Rails mới hơn (ví dụ 5.x), bạn có thể sử dụng phương thức thay đổi thay vì self.upself.down , vì Rails cũng có thể thực hiện khôi phục bằng cách này. Vì vậy, chỉ cần mã này là đủ : def change rename_table :my_table, :my_new_table end. . . . . Bằng cách: Bên trong changebạn một sử dụng các lệnh này: add_column, add_index, add_timestamps, create_table, remove_timestamps, rename_column, rename_index,rename_table
Làm đẹp

2
ActiveRecord::Migration.rename_table(:old_table_name, :new_table_name)
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.