Rails 마이그레이션 : 존재 여부를 확인하고 계속 진행 하시겠습니까?


80

마이그레이션에서 이런 종류의 작업을 수행했습니다.

add_column :statuses, :hold_reason, :string rescue puts "column already added"

그러나 이것이 SQLite에서는 작동하지만 PostgreSQL에서는 작동하지 않는 것으로 나타났습니다 . add_column이 터지면 Exception이 잡혀도 트랜잭션이 종료되어 마이그레이션이 추가 작업을 수행 할 수없는 것 같습니다.

컬럼이나 테이블이 이미 존재하는지 확인 하는 비 DB 분리 방법이 있습니까? 실패하면 구조 블록이 실제로 작동하도록 할 수있는 방법이 있습니까?


조건부 마이그레이션은 롤백 단계에서 포워드 마이그레이션 동안 어떤 조건이 있었는지 알 수 없기 때문에 롤백 문제로 이어진다는 점을 언급해야합니다
oklas

롤백에서 선택 사항이 아닌 부분 만 수행
Dan Rosenstark

답변:


175

Rails 3.0 이상에서는을 사용 column_exists?하여 열의 존재 여부를 확인할 수 있습니다 .

unless column_exists? :statuses, :hold_reason
  add_column :statuses, :hold_reason, :string
end

table_exists?Rails 2.1까지 거슬러 올라가는 함수 도 있습니다 .


추가 / 만들기 전에 열 / 테이블이 존재하는지 확인하는 것이 모범 사례로 간주됩니까? (I 물론 알고는 손에 문제에 따라 다름)
알도 'xoen'Giambelluca

4
변경 방법에서 정의하면 롤백과 함께 작동합니까?
dardub

1
롤백이 문제가 될 수 있습니다. 열을 제거해야하는지 여부를 확신 할 수 없습니다. 이전 상태를 기록하지 않기 때문입니다.
songyy jul.

8

또는 더 짧게

add_column :statuses, :hold_reason, :string unless column_exists? :statuses, :hold_reason

이것은 대답이 아니라 다른 대답에 대한 주석 일 것입니다. 감사.
Dan Rosenstark 2013

4

들어 레일 2.X , 당신은 다음과 컬럼의 존재를 확인할 수 있습니다 :

columns("[table-name]").index {|col| col.name == "[column-name]"}

nil을 반환하면 해당 열이 존재하지 않습니다. Fixnum을 리턴하면 열이 존재하는 것입니다. 당연히 {...}이름보다 더 많은 이름으로 열을 식별하려는 경우 사이에 더 많은 선택적 매개 변수를 넣을 수 있습니다 . 예를 들면 다음과 같습니다.

{ |col| col.name == "foo" and col.sql_type == "tinyint(1)" and col.primary == nil }

(이 답변 은 레일에서 조건부 마이그레이션을 작성하는 방법에 처음 게시 되었습니까? )


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