Làm thế nào để bạn viết một di chuyển để đổi tên một mô hình ActiveRecord và bảng của nó trong Rails?


408

Tôi rất tệ trong việc đặt tên và nhận ra rằng có một bộ tên tốt hơn cho các mô hình của tôi trong ứng dụng Rails của tôi.
Có cách nào để sử dụng di chuyển để đổi tên một mô hình và bảng tương ứng của nó không?


11
Tôi đã đề xuất thêm "ActiveRecord" cho câu hỏi này để cải thiện kết quả khớp của công cụ tìm kiếm. Tôi đã tìm kiếm điều này bằng cách sử dụng "bảng đổi tên ActiveRecord".
Landon Kuhn

6
Nếu bạn đang sử dụng di chuyển, vấn đề này phức tạp hơn dường như. Giải pháp đã chọn cho biết chỉ cần quay lại và đổi tên thủ công mô hình, bộ điều khiển, v.v. sau khi bạn thay đổi tên bảng. Nếu bạn làm điều này, tất cả các di chuyển cũ hơn tham chiếu đến mô hình của bạn bằng tên cũ hơn sẽ thất bại. Vì vậy, khi ai đó nhân bản repo của bạn và cố gắng chạy rake db:migrate, nó sẽ thất bại. Bạn có thể quay lại và thay đổi những tên đó trong quá trình di chuyển, nhưng điều đó sẽ trở nên lộn xộn. Bạn có thể tốt hơn là chỉ tạo một mô hình hoàn toàn mới thay vì đổi tên nó.
andrew

4
@andrewhannigan: Không phải là quan điểm của bạn nếu ai đó nhân bản repo của bạn và chỉ chạy rake db:schema:load?
istrasci

3
@istrasci: hoàn toàn. Trong thực tế, việc chạy rake db:migrateđể thiết lập cơ sở dữ liệu từ đầu được khuyến khích tích cực, chính xác là do những lo ngại được chỉ ra bởi andrew.
Giuseppe

Câu trả lời:


584

Đây là một ví dụ:

class RenameOldTableToNewTable < ActiveRecord::Migration
  def self.up
    rename_table :old_table_name, :new_table_name
  end

  def self.down
    rename_table :new_table_name, :old_table_name
  end
end

Tôi đã phải đi và đổi tên tệp khai báo mô hình bằng tay.

Biên tập:

Trong Rails 3.1 & 4, ActiveRecord::Migration::CommandRecorderbiết cách đảo ngược di chuyển rename_table, vì vậy bạn có thể làm điều này:

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

(Bạn vẫn phải thực hiện và đổi tên thủ công các tệp của mình.)


6
@mathee: có, bạn phải thay đổi điều đó bằng tay hoặc sử dụng IDE có thể thực hiện tái cấu trúc Ruby và cam kết nó với hệ thống kiểm soát phiên bản của bạn.
Pupeno

13
git grep là bạn của bạn. Tôi đang đổi tên một Hoạt động thành Thói quen ngay bây giờ: git grep -i activitrất lộ liễu.
Felix Rabe

1
bạn cũng phải thay đổi nội dung của bộ điều khiển của bạn, phải không?
alemur

5
Và đừng quên tuyến đường của bạn.rb!
Dan Herman

26
Ngoài ra, chỉ cần ngẩng cao đầu, bạn muốn sử dụng phiên bản số nhiều của tên bảng của mình trong lệnh gọi rename_table.
Hân

66

Trong Rails 4, tất cả những gì tôi phải làm là thay đổi def

def change
  rename_table :old_table_name, :new_table_name
end

Và tất cả các chỉ số của tôi đã được chăm sóc cho tôi. Tôi không cần cập nhật thủ công các chỉ mục bằng cách xóa các chỉ mục cũ và thêm các chỉ mục mới.

Và nó hoạt động bằng cách sử dụng thay đổi để tăng hoặc giảm liên quan đến các chỉ mục.


47

Các câu trả lời và nhận xét khác bao gồm việc đổi tên bảng, đổi tên tệp và chuyển qua mã của bạn.

Tôi muốn thêm một vài cảnh báo:

Chúng ta hãy sử dụng một ví dụ thực tế mà tôi phải đối mặt ngày hôm nay: đổi tên một mô hình từ 'Người bán' thành 'Doanh nghiệp'.

  • Đừng quên thay đổi tên của các bảng và mô hình phụ thuộc trong cùng một di chuyển. Tôi đã thay đổi mô hình Merchant và MerchantStat của mình thành Business và BusinessStat cùng một lúc. Nếu không, tôi đã phải chọn quá nhiều cách chọn và lựa chọn khi thực hiện tìm kiếm và thay thế.
  • Đối với bất kỳ mô hình nào khác phụ thuộc vào mô hình của bạn thông qua khóa ngoại, tên cột khóa ngoài của các bảng khác sẽ được lấy từ tên mô hình ban đầu của bạn. Vì vậy, bạn cũng sẽ muốn thực hiện một số cuộc gọi rename_column trên các mô hình phụ thuộc này. Chẳng hạn, tôi đã phải đổi tên cột 'merchant_id' thành 'business_id' trong các bảng tham gia khác nhau (cho mối quan hệ has_and_belongs_to_many) và các bảng phụ thuộc khác (cho các mối quan hệ has_one và has_many bình thường). Nếu không, tôi đã kết thúc với các cột như 'business_stat.merchant_id' chỉ vào 'business.id'. Đây là một câu trả lời tốt về việc đổi tên cột.
  • Khi grepping, hãy nhớ tìm kiếm các phiên bản số ít, số nhiều, viết hoa, viết thường và thậm chí UPPERCASE (có thể xảy ra trong các bình luận) các chuỗi của bạn.
  • Trước tiên, tốt nhất là tìm kiếm các phiên bản số nhiều, sau đó là số ít. Theo cách đó, nếu bạn có số nhiều bất quy tắc - chẳng hạn như trong các thương nhân của tôi :: ví dụ về doanh nghiệp - bạn có thể nhận được tất cả các số nhiều bất quy tắc chính xác. Nếu không, bạn có thể kết thúc với, ví dụ, 'doanh nghiệp' (3 giây) ở trạng thái trung gian, dẫn đến việc tìm kiếm và thay thế nhiều hơn.
  • Đừng mù quáng thay thế mọi sự xuất hiện. Nếu tên mô hình của bạn xung đột với các thuật ngữ lập trình phổ biến, với các giá trị trong các mô hình khác hoặc với nội dung văn bản trong chế độ xem của bạn, bạn có thể sẽ quá háo hức. Trong ví dụ của tôi, tôi muốn thay đổi tên mô hình của mình thành 'Doanh nghiệp' nhưng vẫn gọi họ là 'thương nhân' trong nội dung trong Giao diện người dùng của tôi. Tôi cũng có vai trò 'người bán' cho người dùng của mình trong CanCan - đó là sự nhầm lẫn giữa vai trò người bán và mô hình Người bán khiến tôi đổi tên mô hình ngay từ đầu.

26

Bạn cũng cần thay thế các chỉ mục của mình:

class RenameOldTableToNewTable< ActiveRecord:Migration
  def self.up
    remove_index :old_table_name, :column_name
    rename_table :old_table_name, :new_table_name
    add_index :new_table_name, :column_name
  end 

  def self.down
    remove_index :new_table_name, :column_name
    rename_table :new_table_name, :old_table_name
    add_index :old_table_name, :column_name
  end
end

Và đổi tên các tập tin của bạn, vv, bằng tay như các câu trả lời khác ở đây mô tả.

Xem: http://api.rubyonrails.org/groupes/ActiveRecord/Migration.html

Hãy chắc chắn rằng bạn có thể quay lại và cuộn về phía trước sau khi bạn viết di chuyển này. Nó có thể trở nên khó khăn nếu bạn gặp phải điều gì đó sai và bị mắc kẹt với việc di chuyển cố gắng thực hiện điều gì đó không còn tồn tại. Tốt nhất dọn rác toàn bộ cơ sở dữ liệu và bắt đầu lại nếu bạn không thể quay lại. Vì vậy, hãy lưu ý rằng bạn có thể cần phải sao lưu một cái gì đó.

Ngoài ra: kiểm tra lược đồ_db cho bất kỳ tên cột có liên quan trong các bảng khác được xác định bởi has_ ​​hoặc poss_to hoặc một cái gì đó. Có lẽ bạn cũng cần chỉnh sửa chúng.

Và cuối cùng, làm điều này mà không có bộ kiểm tra hồi quy sẽ là điều tồi tệ.


11
Đối với việc di chuyển đường ray 4.0.0.beta1, không cần thiết phải cập nhật chỉ mục theo cách thủ công. AR tự cập nhật nó.
freemanoid

1

Bạn có thể thực hiện lệnh này: rails g di chuyển rename_ {old_table_name} thành {new_table_name}

sau khi bạn chỉnh sửa tệp và thêm mã này vào thay đổi phương thức

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.