Rails에서 "has_many : through"관계를 언제 사용합니까?


123

나는 그것이 무엇 has_many :through이며 언제 사용 해야하는지 (그리고 어떻게) 이해하려고 노력하고 있습니다. 그러나 나는 그것을 얻지 못하고있다. 저는 Beginning Rails 3을 읽고 인터넷 검색을 시도했지만 이해할 수 없습니다.

답변:


177

두 모델을 가지고 말 : UserGroup.

사용자가 그룹에 속하도록하려면 다음과 같이 할 수 있습니다.

class Group < ActiveRecord::Base
  has_many :users
end

class User < ActiveRecord::Base
  belongs_to :group
end

연결에 대한 추가 메타 데이터를 추적하려면 어떻게해야합니까? 예를 들어 사용자가 그룹에 가입했을 때 또는 그룹에서 사용자의 역할은 무엇입니까?

여기에서 연결을 첫 번째 클래스 개체로 만듭니다.

class GroupMembership < ActiveRecord::Base
  belongs_to :user
  belongs_to :group

  # has attributes for date_joined and role
end

이렇게하면 새 테이블이 도입 group_id되고 사용자 테이블에서 열이 제거 됩니다.

이 코드의 문제점은 사용자 클래스를 사용하는 다른 모든 곳에서 업데이트하고 변경해야한다는 것입니다.

user.groups.first.name

# becomes

user.group_memberships.first.group.name

이러한 유형의 코드는 짜증스럽고 이와 같은 변경 사항을 도입하는 것을 어렵게 만듭니다.

has_many :through 두 가지 장점을 모두 제공합니다.

class User < ActiveRecord::Base
  has_many :groups, :through => :group_memberships  # Edit :needs to be plural same as the has_many relationship   
  has_many :group_memberships
end

이제 일반으로 취급 할 수 has_many있지만 필요할 때 연관 모델의 이점을 얻을 수 있습니다.

을 사용하여이 작업을 수행 할 수도 있습니다 has_one.

편집 : 사용자를 그룹에 쉽게 추가

def add_group(group, role = "member")
  self.group_associations.build(:group => group, :role => role)
end

2
여기 user에서 그룹을 추가하기 위해 모델에 메서드 를 추가합니다. 내가 방금 편집 한 것과 같은 것. 도움이 되었기를 바랍니다.
Ben Scheirman

나도 써야 user.groups << group하나요? 아니면이 협회에서 모든 것을 처리합니까?
LuckyLuke

group_membership과 동일한 클래스가 있는데 팩토리 걸을 사용하는 데 문제가 있는데 도움이 될까요?
Ayman Salah

"has_many : group_memberships"를 사용합니다. 단수를 사용하면 작동하지만 user.group_membership은 컬렉션이되고 user.group_memberships는 작동하지 않습니다.
calasyr

오타였습니다. 결정된.
Ben Scheirman

212

다음 모델이 있다고 가정합니다.

Car
Engine
Piston

자동차 has_one :engine
엔진 belongs_to :car
엔진 has_many :pistons
피스톤belongs_to :engine

자동차 has_many :pistons, through: :engine
피스톤has_one :car, through: :engine

기본적으로 모델 관계를 다른 모델에 위임하므로을 호출하는 대신 다음을 car.engine.pistons수행 할 수 있습니다.car.pistons


9
이것은 완전히 말이됩니다!
RajG 2014 년

24
나는 이것을 SACA-ShortAndClearAnswer라고 부릅니다.
Asme Just

18

ActiveRecord 조인 테이블

has_many :through그리고 has_and_belongs_to_many관계 는 다른 테이블 간의 관계를 나타내는 중간 테이블 인 조인 테이블을 통해 기능합니다 . JOIN 쿼리와 달리 데이터는 실제로 테이블에 저장됩니다.

실질적인 차이점

를 사용하면 has_and_belongs_to_many기본 키가 필요하지 않으며 ActiveRecord 모델을 통하지 않고 ActiveRecord 관계를 통해 레코드에 액세스합니다. 일반적으로 다 대다 관계로 두 모델을 링크하려는 경우 HABTM을 사용합니다.

has_many :through기본 키와 결합 된 데이터에 사용자 지정 열을 추가하는 기능을 갖춘 Rails 모델로 조인 테이블과 상호 작용하려는 경우 관계를 사용합니다 . 후자는 조인 된 행과 관련이 있지만 실제로는 관련 모델에 속하지 않는 데이터 (예 : 조인 된 행의 필드에서 파생 된 계산 된 값 저장)에 특히 중요합니다.

또한보십시오

에서 액티브 레코드 협회에 가이드 , 추천 읽습니다

가장 간단한 경험 법칙은 관계 모델을 독립 엔터티로 사용해야하는 경우 has_many : through 관계를 설정해야한다는 것입니다. 관계 모델에 대해 아무것도 할 필요가없는 경우 has_and_belongs_to_many 관계를 설정하는 것이 더 간단 할 수 있습니다 (데이터베이스에 조인 테이블을 생성하는 것을 기억해야 함).

조인 모델에 대한 유효성 검사, 콜백 또는 추가 속성이 필요한 경우 has_many : through를 사용해야합니다.

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