Rails, 기존 테이블에 대한 null 제약 조건이 있는 add_reference
(10초 꿀팁으로 코딩 문제 풀고 정신건강 예방하는 방법을 배우는 곳) 입니다.
좋은 아침 엔지니어들!
null:false
가 포함된 열을 어떻게 추가하고 기존 레코드에 기본값을 설정하지만 새 레코드가 nil에 대해 유효성이 검사되는지 확인합니다(대신 기본값이 할당됨)?이것은 까다롭게 들리며 나는 당신의 생명을 구하기 위해 여기에 있습니다.
준비가 된?
제약조건이 null:false인 참조 추가
오늘 저는 데이터가 있는 기존 테이블에 검증된 참조 열(일명 외래 키)을 추가하고 싶었습니다. 쉬워요...
add_reference :application_users, :company, index: true, foreign_key: true, null: false
company_id 열의 설정
null: false
은 레코드가 항상 기본값을 가져야 하는 제약 조건을 생성합니다.이것이 바로 내가 원했던 것입니다. 테이블이 비어 있으면 문제가 없습니다.
그러나 기존 레코드의 기본값은 어떻습니까?
위에 표시된 마이그레이션은 마이그레이션을 제공하지 않으면 실패합니다.
-- add_reference(:application_users, :company, {:null=>false, :foreign_key=>true, :index=>true})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:
PG::NotNullViolation: ERROR: column "company_id" contains null values
Caused by:
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: column "company_id" contains null values
Caused by:
PG::NotNullViolation: ERROR: column "company_id" contains null values
제약 조건에 의해 null이 허용되지 않고 다른 기본값이 제공되지 않으면 데이터베이스에서 결정할 다른 방법이 없습니다.
그리고 여기 흥미로운 부분이 있습니다!
기본값 추가, 적절한 방법
id가 1인 회사가 있다는 것을 확실히 알고 있는 경우
default: 1
를 추가하여 기본적으로 해당 회사에 속하도록 모든 기존 레코드를 설정할 수 있습니다.그러나 개발, 스테이징 및 프로덕션과 같은 여러 환경이 있으면
Company
모델을 사용하고 이 모델에서 값을 검색해야 합니다.그래서, 나는 이런 식으로 하기로 결정했습니다...
default_company_id = Company.first.try(:id) || Company.create(name: 'Default company').id
add_reference :application_users, :company, index: true, foreign_key: true, null: false, default: default_company_id
하지만 아직 끝나지 않았다는 것을 알았습니다!
새 레코드가
default: default_company_id
에 할당되는 것을 원하지 않습니다. 대신 데이터베이스가 거래를 검증하고 회사가 제공되지 않으면 정상적으로 실패하기를 원합니다.그래서 한 줄을 추가했습니다.
default_company_id = Company.first.try(:id) || Company.create(name: 'Default company').id
add_reference :application_users, :company, index: true, foreign_key: true, null: false, default: default_company_id
# set default back to nil
change_column_default :application_users, :company_id, nil
이렇게 하면 기본값이 다시 nil로 설정되고 제약 조건이 여전히 존재하므로 company_id 없이 ApplicationUser를 생성하면 예상대로 예외가 발생합니다.
엄청난! 끝났어!
중요한 참고 사항
일반적으로 마이그레이션에서 모델 클래스를 사용하는 것은 안티 패턴으로 간주됩니다.
저는 여기에서 Rails 4를 사용하고 있으며 최신 버전의 Rails에서는 ApplicationRecord에서 상속하는 익명 클래스를 만든 다음 명시적으로 다음과 같이 테이블 이름을 그룹으로 설정할 수 있습니다.
default_company_id = Class.new(ApplicationRecord)
.tap { |c| c.table_name = :companies }
.find_or_create_by(name: 'Default company')
.id
도움이 되었나요?
친구/동료/형제 자매와 공유하십시오.
안녕히 계세요,
중.
Reference
이 문제에 관하여(Rails, 기존 테이블에 대한 null 제약 조건이 있는 add_reference), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/mattiaorfano/rails-addreference-with-null-constraint-on-existing-table-4n6n텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)