2010-12-31 2 views
0

Je suis dans une situation où je dois obtenir tous articles qui sont liés à un User à 2 tables:Choisir parmi plusieurs tables dans Rails - A de nombreux "articles" à travers [table_1, table_2]?

  1. article_access: donne le privilège aux utilisateurs de voir un article
  2. article_favorites: des articles publics, les utilisateurs ont ces favorited

Alors ActiveRecord vous pourriez avoir ceci:

class User < ActiveRecord::Base 
    has_many :article_access_tokens 
    has_many :article_favorites 

    def articles 
    unless @articles 
     ids  = article_access_tokens.all(:select => "article_id").map(&:article_id) + article_favorites.all(:select => "article_id").map(&:article_id) 
     @articles = Article.send(:scoped, :conditions => {:id => ids.uniq}) 
    end 

    @articles 
    end 
end 

Cela me donne essentiellement une association articles qui lit à partir de deux tables distinctes. La question est cependant, quelle est la droite façon de faire cela? Puis-je d'une manière ou d'une autre faire 1 appel SQL SELECT pour cela?

Répondre

1

Eh oui, vous pouvez écrire un joint à ce faire, quelque chose comme:

Article.all(:joins => "left join article_access_tokens on (article_access_tokens.article_id = articles.id and article_access_tokens.user_id = #{self.id}) 
         left join article_favourites on (article_favourites.article_id = articles.id and article_favourites.user_id = #{self.id})", 
      :conditions => "article_favourites.id is not null or article_access_tokens.id is not null") 

doit être une jointure gauche depuis un article pourrait être dans une ou aucune des deux tables (les conditions prises clause le cas où il n'y en a aucun). Cela peut aboutir à des résultats en double si vous n'avez pas une contrainte unique sur article_favourites article_id/user_id et article_access_tokens article_id/user_id, si c'est le cas, il est préférable de corriger les données et d'ajouter la contrainte unique plutôt que de faire un distinct. Pour la propreté, vous pouvez probablement avoir has_many: authorized_articles ou une portée sur le modèle d'article qui prend l'user_id comme paramètre.

Questions connexes