Rails has_and_belongs_to_many 마이그레이션


119

두 가지 모델이 restaurant있고 userhas_and_belongs_to_many 관계를 수행하고 싶습니다.

이미 모델 파일로 이동하여 has_and_belongs_to_many :restaurantshas_and_belongs_to_many :users

이 시점에서 Rails 3과 같은 작업을 할 수 있어야한다고 가정합니다.

rails generate migration ....

그러나 내가 시도한 모든 것이 실패한 것 같습니다. 저는 이것이 정말 간단한 일이라고 확신합니다. 저는 rails를 처음 접하기 때문에 여전히 배우고 있습니다.

답변:


260

restaurant_iduser_id(기본 키 없음) 만있는 별도의 조인 테이블을 알파벳 순서 로 추가해야합니다 .

먼저 마이그레이션을 실행 한 다음 생성 된 마이그레이션 파일을 편집하십시오.

레일즈 3

rails g migration create_restaurants_users_table

레일스 4 :

rails g migration create_restaurants_users

레일즈 5

rails g migration CreateJoinTableRestaurantUser restaurants users

로부터 문서 :

JoinTable이 이름의 일부인 경우 조인 테이블을 생성하는 생성기도 있습니다.


마이그레이션 파일 (참고 :id => false: 기본 키 생성을 방지합니다) :

레일즈 3

class CreateRestaurantsUsers < ActiveRecord::Migration
  def self.up
    create_table :restaurants_users, :id => false do |t|
        t.references :restaurant
        t.references :user
    end
    add_index :restaurants_users, [:restaurant_id, :user_id]
    add_index :restaurants_users, :user_id
  end

  def self.down
    drop_table :restaurants_users
  end
end

레일스 4

class CreateRestaurantsUsers < ActiveRecord::Migration
  def change
    create_table :restaurants_users, id: false do |t|
      t.belongs_to :restaurant
      t.belongs_to :user
    end
  end
end

t.belongs_to필요한 인덱스가 자동으로 생성됩니다. def change앞으로 또는 롤백 마이그레이션을 자동으로 감지하므로 업 / 다운이 필요하지 않습니다.

레일즈 5

create_join_table :restaurants, :users do |t|
  t.index [:restaurant_id, :user_id]
end

참고 :라는 create_join_table에 매개 변수로 전달할 수있는 사용자 정의 테이블 이름에 대한 옵션도 있습니다 table_name. 로부터 문서

기본적으로 조인 테이블의 이름은 알파벳 순서로 create_join_table에 제공된 처음 두 인수의 합집합에서 가져옵니다. 테이블 이름을 사용자 정의하려면 : table_name 옵션을 제공하십시오.


8
@Dex-호기심에서 역순으로 정의 된 두 번째 복합 인덱스를 사용하는 이유를 설명해 주시겠습니까? 나는 칼럼 순서가 중요하지 않다는 인상을 받았다. 저는 DBA가 아니며 제 자신의 이해를 넓히고 싶습니다. 감사!
plainjimbo 2012

11
@Jimbo 그런 식으로 필요하지 않으며 실제로 쿼리에 따라 다릅니다. 인덱스는 왼쪽에서 오른쪽으로 읽으므로에서 검색하는 경우 첫 번째 인덱스가 가장 빠릅니다 restaurant_id. 두 번째는에서 검색하는 경우 도움이됩니다 user_id. 둘 다 검색하는 경우 데이터베이스가 하나만 필요할만큼 똑똑하다고 생각합니다. 그래서 나는 두 번째 것은 정말로 합성 할 필요가 없다고 생각합니다. 이것은 단지 예일뿐입니다. 이것은 Rails 질문 이었으므로 DB 섹션에 게시하면 더 완전한 답변을 얻을 수 있습니다.
Dex

3
두 번째 색인에는 약간의 중복성이 있습니다. restaurant_id와 user_id 모두에 대해 쿼리하는 한 SQL에서의 순서는 중요하지 않으며 첫 번째 색인이 사용됩니다. restaurant_id에 대해서만 쿼리하는 경우에도 사용됩니다. 두 번째 인덱스는 : user_id에만 있어야하며 user_id (키 순서 때문에 첫 번째 인덱스가 도움이되지 않는)에서만 쿼리하는 경우에 사용됩니다.
Yardboy

13
레일 4에서 마이그레이션해야 rails g migration create_restaurants_users없이 테이블 끝에서.
Fa11enAngel 2013-08-23

6
rails g migration CreateJoinTableRestaurantUser 레스토랑 사용자를 사용할 수도 있습니다. 읽기 guides.rubyonrails.org/migrations.html#creating-a-join-table
eKek0

36

여기에 대한 답변은 상당히 오래되었습니다. Rails 4.0.2부터 마이그레이션은 create_join_table.

마이그레이션을 작성하려면 다음을 실행하십시오.

rails g migration CreateJoinTableRestaurantsUsers restaurant user

그러면 다음이 생성됩니다.

class CreateJoinTableRestaurantsUsers < ActiveRecord::Migration
  def change
    create_join_table :restaurants, :users do |t|
      # t.index [:restaurant_id, :user_id]
      # t.index [:user_id, :restaurant_id]
    end
  end
end

이러한 열을 인덱싱하려면 각 줄의 주석 처리를 제거하면됩니다.


2
나는 일반적으로 인덱스 라인 중 하나를 주석 해제하고 추가 unique: true합니다. 이렇게하면 중복 관계가 생성되지 않습니다.
토비 1 케노비

26

조인 테이블을 생성 할 때 마이그레이션 이름 / 클래스에서 두 테이블을 알파벳 순서 로 나열해야한다는 요구 사항에주의하십시오 . 예를 들어 "abc"및 "abb"와 같이 모델 이름이 비슷하면 쉽게 물릴 수 있습니다. 실행한다면

rails g migration create_abc_abb_table

당신의 관계는 예상대로 작동 하지 않을 것입니다. 당신은 사용해야합니다

rails g migration create_abb_abc_table

대신.


1
어느 것이 먼저입니까? foo 또는 foo_bar?
B Seven

1
레일스 콘솔에서 실행 : [ "foo_bar", "foo", "foo bar"]. sort # => [ "foo", "foo bar", "foo_bar"] Unix 정렬도 동일하게 나타납니다.
Shadoath

6

HABTM 관계의 경우 조인 테이블을 만들어야합니다. 조인 테이블 만 있으며 해당 테이블에는 ID 열이 없어야합니다. 이 마이그레이션을 시도하십시오.

def self.up
  create_table :restaurants_users, :id => false do |t|
    t.integer :restaurant_id
    t.integer :user_id
  end
end

def self.down
  drop_table :restaurants_users
end

이 관계 레일 가이드 자습서를 확인해야합니다.


나는 당신이 모델이 필요하다고 생각하지 않으며 HABTM 관계를 위해 모델이 필요하다는 링크에 아무것도 보이지 않습니다.
B Seven

1
생성 된 쿼리의 속도를 높이려면 id 필드에 인덱스를 추가하십시오.
마틴 로버트
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.