2013-04-24 14 views
6

Ho una situazione in cui ho un documento principale e voglio avere due diversi tipi di documenti incorporati: uno come genitore, e un altro come un bambino con un genitore facoltativo. Per esempio:Mongoide: come implementare una relazione tra i documenti incorporati?

class ParentDoc 
    include Mongoid::Document 
    embeds_many :special_docs 
    embeds_many :special_doc_groupings 
end 

class SpecialDoc 
    include Mongoid::Document 
    embedded_in :parent_doc 
    belongs_to :special_doc_groupings 
end 

class SpecialDocGrouping 
    include Mongoid::Document 
    embedded_in :parent_doc 
    has_many :special_docs 
end 

In questo esempio, SpecialDocs e SpecialDocGroupings possono esistere senza una relazione, o, in alternativa può avere una relazione padre-figlio.

Tuttavia, questo è un'associazione Mongoid valida perché otteniamo questo errore:

Mongoid::Errors::MixedRelations:

Problem: Referencing a(n) SpecialDoc document from the SpecialDocGrouping document via a relational association is not allowed since the SpecialDoc is embedded.

Summary: In order to properly access a(n) SpecialDoc from SpecialDocGrouping the reference would need to go through the root document of SpecialDoc. In a simple case this would require Mongoid to store an extra foreign key for the root, in more complex cases where SpecialDoc is multiple levels deep a key would need to be stored for each parent up the hierarchy.

Resolution: Consider not embedding SpecialDoc, or do the key storage and access in a custom manner in the application code.

non vedo niente di sbagliato con il tipo di associazione che sto cercando di creare, oltre al fatto che si tratta di non supportato da Mongoid.

Come posso implementare questo tipo di associazione da solo?

+0

yaa destra non puoi definire questo tipo di associazione in mongoid per quanto riguarda la tua domanda 'ho implementare questo tipo di associazione me stesso?' Ben aver sentito [estendere] (http://guides.rubyonrails.org/association_basics.html#extend) nell'associazione activerecord puoi implementare qualcosa del genere o estendere se mongoid supporta anche qualcosa del genere (controllerò e ti farò sapere di questo) Cheers – Viren

risposta

10

L'associazione non è valida perché quando si fa riferimento al modello incorporato, Mongoid non memorizza la chiave genitore come chiave esterna. Questo significa che se si dispone di:

Class Parent   
    embeds_many :children 
end 

Class Child 
    embedded_in :parent 
end 

Non è possibile fare riferimento documento Bambino memorizzare solo la sua chiave esterna, ma è necessario memorizzare tutte le chiavi genitori fino a raggiungere la radice. In questo caso la radice è rappresentata dal primo genitore ed è necessario memorizzare 2 chiavi.

È possibile eseguire manualmente questo e creare questo tipo di associazione senza alcun problema.

Il tuo caso è un po 'diverso (e più semplice) perché vuoi creare l'associazione tra due modelli incorporati nello stesso genitore. Ciò significa che in teoria non è necessario memorizzare la chiave genitore perché i modelli condividono la stessa radice. Mongoid non gestisce questo scenario, quindi è necessario creare manualmente le regole e i metodi dell'associazione.

Class Bar 
    embeds_many :beers 
    embeds_many :glasses 
end 

Class Beer 
    embedded_in :bar 
    # Manual has_many :glasses association 
    def parent 
    self.bar 
    end 

    def glasses 
    parent.glasses.where(:beer_id => self.id) 
    end 

end 

Class Glass 
    embedded_in :bar 
    # Manual belongs_to :beer association 
    field :beer_id, type: Moped::BSON::ObjectId 
    def parent 
     self.bar 
    end 

    def beer 
     parent.beers.find(self.beer_id) 
    end 
end 

(il codice non è testato)

+1

Non ho capito bene la tua spiegazione, ma la tua soluzione è praticamente identica a quello che mi è venuta in mente. Mi piacciono anche i tuoi nomi di esempio. =] – Andrew

+0

Come procedere in Mongoid se i documenti incorporati che si desidera associare hanno documenti padre diversi? – elsurudo

Problemi correlati