Rails에서 ActiveRecord 모델과 테이블 이름을 바꾸기 위해 마이그레이션을 어떻게 작성합니까?


408

나는 이름을 짓는데 끔찍하며 내 Rails 앱에 더 나은 모델 이름이 있다는 것을 알고 있습니다.
마이그레이션을 사용하여 모델 및 해당 테이블의 이름을 바꾸는 방법이 있습니까?


11
검색 엔진 일치를 개선하기 위해이 질문에 "ActiveRecord"를 추가 할 것을 제안했습니다. "ActiveRecord 이름 바꾸기 테이블"을 사용하여 이것을 찾고 있습니다.
랜던 Kuhn

6
마이그레이션을 사용하는 경우이 문제는 생각보다 복잡합니다. 선택한 솔루션은 테이블 이름을 변경 한 후 모델, 컨트롤러 등으로 돌아가서 수동으로 이름을 바꾸라고 말합니다. 이렇게하면 이전 이름으로 모델을 참조하는 모든 이전 마이그레이션이 실패합니다. 따라서 누군가가 귀하의 저장소를 복제하고 실행하려고 rake db:migrate하면 실패합니다. 되돌아 가서 마이그레이션에서 해당 이름을 변경할 수 있지만 지저분해질 것입니다. 이름을 바꾸는 대신 완전히 새로운 모델을 만드는 것이 좋습니다.
앤드류

4
@ andrewhannigan : 누군가가 당신의 레포를 복제하고 실행하면 포인트가 약하지 rake db:schema:load않습니까?
istrasci

3
@istrasci : 절대적으로. 사실, rake db:migrateAndrew가 지적한 문제로 인해 처음부터 데이터베이스를 처음부터 실행 하는 것은 적극적으로 권장되지 않습니다.
주세페

답변:


584

예를 들면 다음과 같습니다.

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

모델 선언 파일을 수동으로 바꿔야했습니다.

편집하다:

Rails 3.1 & 4에서는 ActiveRecord::Migration::CommandRecorderrename_table 마이그레이션을 취소하는 방법을 알고 있으므로 다음과 같이 할 수 있습니다.

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

(여전히 파일을 수동으로 변경하고 이름을 바꿔야합니다.)


6
@ mathee : 예, 수동으로 변경하거나 Ruby 리팩토링을 수행하고 버전 제어 시스템에 커밋 할 수있는 IDE를 사용해야합니다.
pupeno

13
git grep은 당신의 친구입니다. 나는 지금 활동을 습관으로 바꾸고 git grep -i activit있습니다.
Felix Rabe

1
컨트롤러의 내용도 변경해야합니까?
alemur

5
그리고 routes.rb를 잊지 마십시오!
Dan Herman

26
또한, 헤드 업과 마찬가지로 rename_table 호출에서 여러 버전의 테이블 이름을 사용하려고합니다.

66

Rails 4에서 내가해야 할 일은 데프 변경이었습니다.

def change
  rename_table :old_table_name, :new_table_name
end

그리고 모든 색인이 나를 위해 돌 보았습니다. 이전 인덱스를 제거하고 새 인덱스를 추가하여 인덱스를 수동으로 업데이트 할 필요가 없었습니다.

그리고 인덱스와 관련하여 위 또는 아래로 변경을 사용하여 작동합니다.


47

다른 답변과 의견에는 테이블 이름 바꾸기, 파일 이름 바꾸기 및 코드를 통한 grepping이 포함되었습니다.

몇 가지주의 사항을 추가하고 싶습니다.

오늘 직면 한 실제 예를 사용하여 모델을 '판매자'에서 '비즈니스'로 이름을 바꿉니다.

  • 동일한 마이그레이션에서 종속 테이블 및 모델의 이름을 변경하는 것을 잊지 마십시오. Merchant 및 MerchantStat 모델을 동시에 Business 및 BusinessStat로 변경했습니다. 그렇지 않으면 검색 및 바꾸기를 수행 할 때 너무 많이 선택하고 선택해야했습니다.
  • 외래 키를 통해 모델에 의존하는 다른 모델의 경우 다른 테이블의 외래 키 열 이름은 원래 모델 이름에서 파생됩니다. 따라서 이러한 종속 모델에 대해 rename_column 호출도 수행하려고합니다. 예를 들어, 다양한 조인 테이블 (has_and_belongs_to_many 관계) 및 기타 종속 테이블 (일반 has_one 및 has_many 관계)에서 'merchant_id'열의 이름을 'business_id'로 바꿔야했습니다. 그렇지 않으면 'business_stat.merchant_id'와 같은 열이 'business.id'를 가리키는 것으로 끝났을 것입니다.다음은 열 이름 변경에 대한 좋은 답변입니다.
  • 그 리핑 할 때 문자열의 단수형, 복수형, 대문자, 소문자 및 대문자 (댓글로 표시 될 수 있음) 버전을 검색해야합니다.
  • 먼저 복수 버전을 검색 한 다음 단수를 검색하는 것이 가장 좋습니다. 그렇게하면 내 판매자 :: 비즈니스 사례와 같이 불규칙 복수형이있는 경우 모든 불규칙 복수형을 올바르게 얻을 수 있습니다. 그렇지 않으면 예를 들어 'businesss'(3 s)가 중간 상태로되어 검색 및 교체가 더 많아 질 수 있습니다.
  • 모든 사건을 맹목적으로 교체하지 마십시오. 모델 이름이 일반적인 프로그래밍 용어, 다른 모델의 값 또는 뷰의 텍스트 내용과 충돌하는 경우 너무 열렬해질 수 있습니다. 내 예에서는 모델 이름을 'Business'로 변경하고 싶지만 UI의 컨텐츠에서 모델 이름을 '판매자'라고합니다. 또한 CanCan에서 사용자에게 '판매자'역할이있었습니다. 판매자 역할과 판매자 모델 간의 혼동이 있었기 때문에 처음에 모델 이름을 바 꾸었습니다.

26

또한 인덱스를 교체해야합니다.

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

다른 답변에서 설명하는 것처럼 수동으로 파일 이름을 바꾸십시오.

보다: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html

이 마이그레이션을 작성한 후 롤백 및 롤 포워드 할 수 있는지 확인하십시오. 문제가 발생하여 더 이상 존재하지 않는 항목에 영향을주는 마이그레이션으로 인해 문제가 발생하면 까다로울 수 있습니다. 롤백 할 수없는 경우 전체 데이터베이스를 휴지통에 버리고 다시 시작하십시오. 따라서 무언가를 백업해야 할 수도 있습니다.

또한 has_ ​​또는 belongs_to 등으로 정의 된 다른 테이블의 관련 열 이름에 대해서는 schema_db를 확인하십시오. 아마 그것들도 편집해야 할 것입니다.

마지막으로 회귀 테스트 스위트없이이를 수행하는 것은 쉽지 않습니다.


11
rails 4.0.0.beta1 마이그레이션의 경우 인덱스를 수동으로 업데이트 할 필요가 없습니다. AR은 자체적으로 업데이트합니다.
freemanoid

1

레일 g 마이그레이션 rename_ {old_table_name} :이 명령을 실행 할 수 있습니다 {new_table_name}으로

파일을 편집하고 메소드 변경에이 코드를 추가 한 후

rename_table : {old_table_name}, : {new_table_name}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.