2010-01-02 4 views
2

En ce moment je suis en utilisant une association has_and_belongs_to_many pour deux de mes modèles comme ceci:associations avancées dans les rails

class Books < ActiveRecord::Base 
    has_and_belongs_to_many :publishers 
end 

class Publisher < ActiveRecord::Base 
    belongs_to :publishing_company 
    has_and_belongs_to_many :books 
end 

Vous remarquerez que chaque éditeur appartient à une société d'édition:

class PublishingCompany < ActiveRecord::Base 
    has_many :publishers 
end 

Mon objectif est de mettre en place une association qui me permettrait de faire:

PublishingCompany.find(1).books 

est-ce possible avec les associations RoR conventionnelles?

Répondre

5

Le concept que vous recherchez est de spécifier une association de second degré en utilisant le paramètre: through sur une association has_many de votre classe PublishingCompany. Faire des associations de second degré (qui rejoindra 2 tables supplémentaires) est très commun, je ne pense pas avoir jamais fait d'association de troisième degré (publishers -> publisher_books -> books), et si je me souviens bien, Rails devient assez moche à comprendre ce que vous essayez de faire une fois que vous pousser les associations jusqu'à présent.

La première option qui vaut la peine d'essayer est:

class PublishingCompany 
    has_many :publishers 
    has_many :books, :through => :publishers 
end 

Le Rails documentation indique toutefois que: par le paramètre ne peut être utilisé sur un has_many ou belongs_to, ce qui signifie cela ne devrait pas travailler par l'association has_and_belongs_to_many vous avez . Votre seconde option est ce que je devais faire sur un système que j'ai écrit sur Rails 1. Je vais probablement être rejeté pour cela, mais c'était quelque chose que je devais cuisiner parce que je ne pouvais pas obtenir de rails pour le gérer.

Puisque vous allez seulement utiliser l'association en lecture seule, je viens de créer une fausse méthode pour la gérer. Soyez averti, c'est un dernier recours. En guise de note, je n'aime pas personnellement has_and_belongs_to_many associations car je trouve étrange que vous n'ayez pas d'objets que vous pouvez manipuler qui représentent les lignes de la table de jointure.

class Books 
    has_many :book_publishers 
    has_many :publishers, :through => :book_publishers 
end 

class BookPublisher 
    belongs_to :book 
    belongs_to :publisher 
end 

class Publisher 
    has_many :book_publishers 
    has_many :books, :through => :book_publishers 
    belongs_to :publishing_company 
end 

class PublishingCompany 
    has_many :publishers 
    has_many :book_publishers, :through => :publishers 

    def books 
    book_publishers.map{|bp|bp.book} 
    end 
end 

# typical use, eager loading to avoid N+1 
company = PublishingCompany.first :include => {:book_publishers => :book} 
company.books.each {|b| puts b.title} 
0

Ceci devrait fonctionner pour vous.

class PublishingCompany < ActiveRecord::Base 
    has_many :books, :through => :publishers, :source => :books 
end 

paramètre :source est celui que vous devez utiliser

Questions connexes