Domanda

Sto usando associazioni polimorfiche per monitorare Commenti nel mio progetto. Tutta roba in avanti molto semplice.

Il problema che ho è nella interrogazione sulla base della associazione polimorfica e unendo dal modello Commento di nuovo al suo proprietario.

...

Ho un modello Commento

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

E una modalità ForumTopics:

class ForumTopic < ActiveRecord::Base
  has_many :comments, :as => :commentable
end

Ho diversi altri modelli "commentabile" che non sono importanti in questo momento. Tutto questo funziona.

Quello che sto cercando di fare è trovare tutti i commenti che appartengono ad un ForumTopic con una condizione specificata (in questo caso, 'optional' == true).

Quando provo e uso un cercatore di unire i modelli:

@comments = Comment.find(:all 
            :joins => :commentable
            :conditions => ["forum_topics.featured = ? ", true] 
            )

ricevo il seguente errore:

  

Non può caricare con entusiasmo l'associazione polimorfica: commentabile

Uso della AR "includono sintassi":

@comments = Comment.find(:all 
            :include => :forum_topics
            :conditions => ["forum_topics.featured = ? ", true] 
            )

restituisce:

  

non è stato trovato Associazione denominata 'forum_topics'; forse scritto male vero?

Se provo e unisco con un nome di tabella invece del nome dell'associazione (stringa invece del simbolo):

@comments = Comment.find(:all,
            :joins => "forum_topics",
            :conditions => ["forum_topics.featured = ? ", true] 
            )

Vedo:

  

Mysql :: Errore: 'commenti' tavolo sconosciuta:. Selezionate commenti dai commenti forum_topics WHERE (forum_topics.featured = 1) *

(Si può vedere qui che la sintassi della query sottostante è completamente spento e il join manca del tutto).

Non sono sicuro se quello che sto facendo è ancora possibile, e ci sono altri modi per ottenere il risultato richiesto, ma sembra che dovrebbe essere fattibile.

Tutte le idee? Tutto ciò che mi manca?

È stato utile?

Soluzione

Argh!

Credo di aver trovato il problema.

Quando si uniscono tramite:

@comments = Comment.find(:all,
        :joins => "forum_topics",
        :conditions => ["forum_topics.featured = ? ", true] 
        )

È necessario l'intero unirsi!

:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id",

Si veda la sempre impressionante: http://guides.rubyonrails.org/active_record_querying.html#joining-tables

Altri suggerimenti

Una vecchia questione, ma c'è un modo più pulito di ottenere tale risultato con la creazione di un'associazione diretta per il tipo specifico insieme al polimorfico:

#comment.rb
class Comment < ActiveRecord::Base

  belongs_to :commentable, polymorphic: true
  belongs_to :forum_topics, -> { where( comments: { commentable_type: 'ForumTopic' } ).includes( :comments ) }, foreign_key: 'commentable_id'

  ...

end

Si sono quindi in grado di passare a :forum_topics includes sbarazzarsi della necessità di un disordinato join:

@comments = Comment
  .includes( :forum_topics )
  .where( :forum_topics => { featured: true } )

Si potrebbe quindi pulire ulteriormente questo in su spostando la query in un campo di applicazione:

#comment.rb
class Comment < ActiveRecord::Base

  ...

  scope :featured_topics, -> { 
    includes( :forum_topics )
    .where( :forum_topics => { featured: true } ) 
  }

  ...

end

lasciando di essere in grado di fare semplicemente

@comments = Comment.featured_topics

Hai bisogno di una condizionale, più il Rails 3 +

Un sacco di gente accennato nelle risposte e commenti, ma ho sentito che le persone, me compreso, otterrebbe sgambetto se ho atterrato qui e non hanno letto abbastanza attentamente.

Quindi, ecco la risposta corretta, tra cui il condizionale che è assolutamente necessario.

@comments = Comment.joins( "INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id" )
                   .where( comments:     { commentable_type: 'ForumTopic' } )
                   .where( forum_topics: { featured:         true         } )

Grazie a tutti, specialmente @Jits, @Peter e @prograils per i loro commenti.

La soluzione accettata non funziona una volta che si introduce un altro modello che ha un'associazione con "commentabile". commentable_id non è unico e quindi potrai iniziare il recupero dei commenti sbagliati.

Ad esempio:

Si decide di aggiungere un modello di notizie che accetta commenti ...

class News < ActiveRecord::Base
   has_many :comments, :as => :commentable
end

Ora si può ottenere due record indietro se hai fatto un commento su un forum_topic con un ID di 1 e un articolo di notizie con un ID di 1 utilizzando query:

:joins => "INNER JOIN forum_topics ON forum_topics.id = comments.commentable_id"

Si potrebbe forse risolvere il problema fornendo una commentable_type come una delle vostre condizioni, ma non credo che sia il modo migliore per affrontare questo problema.

Mi sono imbattuto in questo post e mi portano a mia soluzione. Utilizzando la commentable_type come una delle mie condizioni, ma utilizzando un join esterno sinistro, invece. saranno inclusi che gli argomenti del forum modo senza commenti.

LEFT OUTER JOIN `comments` ON `comments`.`commentable_id` = `forum_topics`.`id` AND `comments`.`commentable_type` = 'ForumTopic'

Controllato a lavorare sotto Rails 5 :

Soluzione 1:

@comments = Comment
              .where(commentable_type: "ForumTopic")
              .joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id")
              .where(forum_topics: {featured: true})
              .all

o

Soluzione 2:

@comments = Comment
              .joins("INNER JOIN forum_topics ON comments.commentable_id = forum_topics.id AND comments.commentable_type = 'ForumTopic'")
              .where(forum_topics: {featured: true}).all

Attenzione alla sintassi SQL grezzo: nessun backticks sono ammessi. Vedere http://guides.rubyonrails.org/active_record_querying.html#joining-tables.

Io personalmente preferisco Soluzione 1 in quanto contiene meno sintassi SQL crudo.

Rails non include un polimorfica unirsi per default, ma questo gioiello aiuterebbe a si unisce alla tua relazione polimorfica con facilità. https://github.com/jameshuynh/polymorphic_join

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top