2009-04-22 7 views
1

ActiveRecord가 단순한 has_many, belongs_to 등보다 복잡한 연결을 처리하는 방법을 이해하려고합니다.ActiveRecord 모델의 복잡한 연결

예를 들어, 음악 작곡을 녹음하는 응용 프로그램을 고려해보십시오. 각 공연에는 장르가있는 밴드가 있습니다. 각 공연에는 또한 지역이있는 장소가 있습니다. (갑자기위한 매우 향수를 느끼기 시작 해요) MS 액세스의 거친 표기에서

이러한 관계는 같이 제시 될 것입니다이

 1 ∞  1 ∞  ∞ 1  ∞ 1 
Genre ---- Band ---- Gig ---- Venue ---- Region 
내가 예를 들어, 찾을 수 있도록하고 싶습니다

, 한 지역에서 연주 한 모든 밴드 또는 특정 장르를 개최하는 모든 장소.

이상적으로, 내 모델이 코드

class Genre 
    has_many :bands 
    has_many :gigs, :through => bands 
    has_many :venues, :through => :gigs, :uniq => true 
    has_many :regions, :through => :venues, :uniq => true 
end 

class Band 
    belongs_to :genre 
    has_many :gigs 
    has_many :venues, :through => :gigs, :uniq => true 
    has_many :regions, :through => :venues, :uniq => true 
end 

class Gig 
    belongs_to :genre, :through => :band 
    belongs_to :band 
    belongs_to :venue 
    belongs_to :region, :through => :venue 
end 

VenueRegion에 포함됩니다. 일반적으로 하나 하나의 특정 -

그러나, 나는이 대신

class Genre 
    has_many :bands 
    has_many :gigs, :through => bands 
    has_many :venues, :finder_sql => "SELECT DISTINCT venues.* FROM venues " + 
    "INNER JOIN gigs ON venue.id = gig.venue_id " + 
    "INNER JOIN bands ON band.id = gig.band_id " + 
    "WHERE band.genre_id = #{id}" 
    # something even yuckier for regions 
end 

class Band 
    belongs_to :genre 
    has_many :gigs 
    has_many :venues, :through => :gigs, :uniq => true 
    # some more sql for regions 
end 

class Gig 
    delegate :genre, :to => :band 
    belongs_to :band 
    belongs_to :venue 
    delegate :region, :to => :venue 
end 

나는이 개 질문이 같은 것을 생산해야 할 것으로 보인다.

일반

:

나는 꽤 자주 와서 일을하려고 무슨 생각했을 것이다. 내가 할 수있는 최선의 방법은 무엇인가, 아니면 내가 간과하고있는 것보다 훨씬 간단한 것이 있습니까?

특히 :

내가 실제로 가지고있는 것은 실제로 작동하지 않습니다! 두 번째 장르 모델의 #{id}은 실제로 클래스의 ID를 반환합니다. (나는 생각한다). 그러나 이것은 작동하는 것 같다 herehere

나는 이것이 오히려 서사시적인 질문이라는 것을 알고있다. 당신이 이것을 가지고 있다면 고맙다. 어떤 도움이라도 대단히 감사하겠습니다!

답변

0

이와 같은 연관성에 대해 사용자 지정 SQL을 작성하게 될 것입니다. 상당히 대규모 조인을 수행하지 않고도 이와 같은 연결 체인을 처리 할 수있는 실제 방법이 없습니다. 실제로는 없습니다. 내장 된 쿼리 생성기가 한 줄짜리 코드로이를 처리하는 효율적인 방법입니다.

ActiveRecord의 : joins 매개 변수도 살펴볼 수 있습니다. 원하는대로 할 수 있습니다.

3

연관성은 읽을 수 있도록 설계되었습니다. 및 쓰기 가능. 그 가치의 상당 부분은 다음과 같이 할 수 있다는 것입니다.

@band.gigs << Gig.new(:venue => @venue) 

읽기 전용 인 것처럼 들리 겠지만. 즉, 장소 및 장르를 연결하고 싶지만 수행하지 않을 것입니다.

@venue.genres << Genre.new("post-punk") 

이는 의미가 없기 때문입니다. 특정 장르의 밴드가 거기있는 곳이라면 Venue에만 장르가 있습니다.

연결이 쓰기 가능해야하므로 연관성이 작동하지 않습니다. 다음은 내가 읽기 전용 협회를 운영하는 방법입니다 :

class Genre 
    has_many :bands 

    def gigs 
    Gig.find(:all, :include => 'bands', 
      :conditions => ["band.genre_id = ?", self.id]) 
    end 

    def venues 
    Venue.find(:all, :include => {:gigs => :band}, 
     :conditions => ["band.genre_id = ?", self.id]) 
    end 
end 
0

nested_has_many_through의 직장과 같은 소리입니다! 중첩 할 수있는 훌륭한 플러그인 has_many :throughs

1

연결에 조건과 매개 변수를 추가 할 수 있습니다. 최근 버전의 ActiveRecord는 named_scopes의 힘을 제공하며 관련 레코드에서도 작동합니다. 현재 프로젝트

Folder has_many Pages 
Page has_many Comments 

# In Page 
named_scope :commented, 
    :include => "comments", 
    :conditions => ["comments.id IS NULL OR comments.id IS NOT NULL"], 
    :order => "comments.created_at DESC, pages.created_at DESC" 

에서

우리가 말할 수있는이 사용 :

folder.pages.commented 

어느 것 제공된 매개 변수와 조건부을하고 관련 기록에 대한 범위.

Plus! named_scopes는 구성 가능합니다.

그리고 더 범위 :

named_scope :published, :conditions => ["forum_topics.status = ?", "published"] 

와 함께 그들을 체인 : 이

을 folder.pages.published.commented
관련 문제