여러 열의 고유성 확인


193

실제 레코드가 열이 아니라 고유한지 확인하는 레일 웨이 방법이 있습니까? 예를 들어, 우정 모델 / 테이블은 다음과 같은 여러 개의 동일한 레코드를 가질 수 없습니다.

user_id: 10 | friend_id: 20
user_id: 10 | friend_id: 20

7
내가 조밀하다면 저를 용서하십시오. 그러나이 상황에서 어떻게 도움이 되겠습니까?
re5et

2
모델에서 "validates_uniqueness_of"를 사용해보십시오. 이 방법으로 문제가 해결되지 않으면 add_index : table, [: column_a, : column_b], : unique => true)와 같은 문장을 포함하는 feilds의 마이그레이션을 생성 할 수있는 인덱스를 만들려고합니다.
Harry Joy

1
@HarryJoy, 그는 물었다 Is there a rails-way way. 그리고 당신은 그에게 비철도 방식을 제공하지만 표준입니다. The Active Record way claims that intelligence belongs in your models, not in the database.
그린

2
불행히도 validates :field_name, unique: true경쟁 조건이 발생하기 쉽기 때문에 철도에 반대하더라도 실제 제약 조건이 선호됩니다. @HarryJoy 제약 방법을 설명하는 대답을 찬성하겠습니다.
Pooyan Khosravi

1
모든 아래 언급 더 나은 대답은 이것이다 stackoverflow.com/a/34425284/1612469 제대로 작동해야합니다 모든 것을 만들기위한 또 다른 레이어를 제공으로
하기 Aleks을

답변:


319

validates_uniqueness_of다음과 같이 통화 범위를 지정할 수 있습니다 .

validates_uniqueness_of :user_id, :scope => :friend_id

83
두 개 이상의 필드에서 고유성을 검증해야하는 경우 여러 범위 매개 변수를 전달할 수 있다고 덧붙였습니다. 즉 : scope => [: friend_id, : group_id]
Dave Rapin

27
말할 수 없다는 것이 이상 validates_uniqueness_of [:user_id, :friend_id]합니다. 패치가 필요할까요?
Alexey

12
Alexey, validates_uniqueness_of [: user_id, : friend_id]는 나열된 각 필드에 대해 유효성 검사를 수행하며 문서화되고 예상되는 동작입니다.
Nikita Hismatov

71
Rails 4에서 이것은 다음과 같이됩니다 : : user_id, 고유성 : {scope : : friend_id}
Marina Martin

3
, : message => 'has already this friend'와 같은 사용자 정의 오류 메시지를 추가하고 싶을 것입니다.
laffuste

137

하나의 열 validates에서 유효성을 검사 하는 데 사용할 수 있습니다 uniqueness.

validates :user_id, uniqueness: {scope: :friend_id}

여러 열에 대한 유효성 검사 구문은 비슷하지만 대신 필드 배열을 제공해야합니다.

validates :attr, uniqueness: {scope: [:attr1, ... , :attrn]}

그러나 위에 표시된 유효성 검사 방식에는 경쟁 조건이 있으며 일관성을 보장 할 수 없습니다. 다음 예제를 고려하십시오.

  1. 데이터베이스 테이블 레코드는 n 개의 필드 로 고유해야 합니다.

  2. 각각 별도의 프로세스 ( 응용 프로그램 서버, 백그라운드 작업자 서버 또는 사용중인 것 )에 의해 처리되는 여러 ( 2 개 이상의 ) 동시 요청, 데이터베이스에 액세스 하여 테이블에 동일한 레코드를 삽입합니다.

  3. 병렬로 각 프로세스는 동일한 n 필드를 가진 레코드가 있는지 검증 합니다.

  4. 각 요청에 대한 유효성 검사가 성공적으로 통과되고 각 프로세스는 동일한 데이터를 사용하여 테이블에 레코드를 만듭니다.

이러한 종류의 동작을 피하려면 db 테이블에 고유 제한 조건 을 추가해야 합니다. 당신은 그것을 설정할 수 있습니다add_index다음 마이그레이션을 실행하여 하나 이상의 필드에 도우미로 .

class AddUniqueConstraints < ActiveRecord::Migration
  def change
   add_index :table_name, [:field1, ... , :fieldn], unique: true
  end
end

주의 사항 : 고유 한 제약 조건을 설정 한 후에도 두 개 이상의 동시 요청이 동일한 데이터를 db에 쓰려고 시도하지만 중복 레코드를 만드는 대신 ActiveRecord::RecordNotUnique예외 가 발생 하여 별도로 처리해야합니다.

begin
# writing to database
rescue ActiveRecord::RecordNotUnique => e
# handling the case when record already exists
end 

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