2013-02-21 18 views
22

In Meteor, quando recuperi un record da un database, è solo un record. Quindi, se ho una raccolta chiamata Dogs, una dog potrebbe avere fur: 'brown' o breath: 'stinky', ma non ha un metodo bark().Qual è il modo migliore per allegare un comportamento a una collezione Meteor?

Ovviamente, è possibile creare alcune funzioni che prevedono uno dog come argomento e quindi eseguire operazioni su tale dog. Potrei anche incapsulare tutte queste funzioni in un singolo costruttore. Non sono pazzo di questo approccio, ma se qualcuno ha un modo pulito e sensato per farlo, sono tutto orecchie.

Un altro pensiero che ho avuto è stato quello di avvolgere il dog in un Backbone.Model. Questo potrebbe essere interessante, come fetch e save potrebbe essere ridefinito per fare find e insert o update, e puoi anche definire tutto il tuo comportamento, ma ho letto che questo tipo di cose è generalmente scoraggiato.

C'è un modo giusto per farlo? C'è un Meteor.Model ufficialmente in lavorazione? In che modo gli altri stanno risolvendo questo problema?

Modifica

Per chi arriva a questa domanda più di un anno dopo la risposta accettata: Al momento di questa modifica sto usando Exygy's minimongoid mrt package, che ha alcuni miglioramenti per haihappen's version che è menzionato nel post del blog legati alla dalla risposta accettata.

Attualmente sto contribuendo al repository per rendere i set di risultati più simili a relazioni. Spero che altri ne facciano uso e si sentano propensi a contribuire con utili funzionalità.

Modifica

Un'altra risposta ha suggerito di utilizzare la proprietà transform durante la creazione della collezione. Mentre preferisco decisamente qualcosa che non ho davvero bisogno di costruire da solo, questa funzionalità aggiunge molte possibilità, e mi auguro che tutti i team che stanno lavorando su un ORM per Meteor ne traggano vantaggio al centro .

Here's a blog post spiegazione dell'utilizzo della proprietà transform.

Inoltre, minimongoid is now available as a Meteor package, e lo sto ancora utilizzando. Supporta la convalida e la dichiarazione delle relazioni. Ho aggiunto anche alcune funzionalità a questo pacchetto, quindi se una scheda ha molti pezzi, board.pieces().create(attributes) verrà mantenuto un nuovo record piece con il dato attributes e verrà automaticamente associato allo board. Tra le varie soluzioni che ho visto, questo sembra essere il più completo.

+2

Degno di nota è il [di raccolta-comportamenti] (http://beta.atmospherejs.com/package/collection-behaviours) pacchetto. –

+0

@DanDascalescu, grazie per il link!Non si adatta perfettamente a ciò che sto cercando, ma mi sarebbe molto utile in altri modi. Molto apprezzato! – Samo

risposta

3

Mentre ci potrebbe essere un official model system in the works ci sono alcune cose che puoi fare ora:

C'è uno da Mario Uhler che è ActiveRecord come e piuttosto bella, in CoffeeScript: https://coderwall.com/p/_q9b1w

C'è anche una comunità pacchetto fatto da Tom Coleman che è molto utile con i modelli: https://github.com/tmeasday/meteor-models, potrebbe essere necessario meteorite per aggiungerlo come pacchetto.

E ovviamente come hai suggerito Backbone. Personalmente utilizzo i prototipi di js, ma non tutti possono essere comodi con loro, li ho semplicemente usati per essere facilmente trasferiti quando il sistema di modelli di meteore è fuori, è anche facile da condividere tra client e server senza troppi pacchetti da aggiungere.

+0

Grazie per la risposta. Se non è un problema, puoi fornire un semplice esempio di come sfruttare i prototipi di js per risolvere questo problema? – Samo

+0

L'aggiornerò tra un po ', ho solo bisogno di pulire il prototipo un po' – Akshat

+0

grazie, non vedo l'ora :-) – Samo

4

Questo è un inizio per sovrascrivere Meteor.Collection per supportare i metodi sugli oggetti.

Meteor.Kollection = Meteor.Collection; 
Meteor.Kollection.extend = function(constructor) { 
    var parent = this; 
    var child = function() { 
    Meteor.Kollection.apply(this, arguments); 
    constructor.apply(this, arguments); 
    }; 

    _.extend(child, parent); 

    function __proto__() { this.constructor = child; }; 
    __proto__.prototype = parent.prototype; 
    child.prototype = new __proto__; 

    return child; 
}; 

Meteor.Collection = Meteor.Kollection.extend(function(name, options) { 
    if (options && options.defaults) { 
    this.defaults = options.defaults; 
    } 
}); 

Meteor.Collection.prototype.applyDefaults = function(attrs) { 
    return _.defaults(attrs, this.defaults); 
}; 

Meteor.Collection.prototype.create = function(attrs) { 
    if (typeof attrs !== "object") attrs = {}; 
    return this.applyDefaults(attrs); 
}; 

Meteor.Collection.prototype.findOne = function(selector, options) { 
    var object = Meteor.Kollection.prototype.findOne.apply(this, arguments); 
    return this.applyDefaults(object); 
}; 

Si può notare la nuova collezione metodo .create, e che raccolta .findOne è stato ignorato. Immagino tutti i collezione. * I metodi dovranno essere sovrascritti, ma questo è un inizio.

Quindi cosa si può fare con questo?

var Dogs = new Meteor.Collection("dogs", { defaults: { 
    barkSound: "ruff", 
    bark: function() { 
    console.log(this.barkSound); 
    } 
}}); 

if (Meteor.isClient) { 
    var regularDog = Dogs.create(); 
    regularDog.bark(); // ruff 

    var smallDog = Dogs.create({ 
    barkSound: "yip" 
    }); 
    smallDog.bark(); // yip 

    Dogs.insert(smallDog, function(error, id) { 
    Dogs.findOne(id).bark(); // yip 
    }); 
}); 

Non sono esattamente sicuro di come ciò avvenga, ma tutte le funzioni in un oggetto vengono rimosse quando vengono inserite. Pertanto, possiamo applicare direttamente i metodi all'oggetto. Innanzitutto, crei la tua raccolta passando un oggetto con la proprietà defaults. Questa proprietà può includere proprietà o metodi. Per creare un nuovo oggetto per una determinata collezione, utilizzare la collezione .create (attrs), dove attrs è un argomento di opzioni che include proprietà e metodi aggiuntivi o sovrascritti.

27

È possibile utilizzare il parametro transform nella collezione di sovraccaricare l'oggetto con funzioni personalizzate

var Dogs = new Meteor.Collection("dogs", 
{ 
    transform:function(entry) 
    { 
     entry.bark = function(){ console.log(this.barkSound);}; 
     return entry; 
    } 
}); 

Poi:

var aDogID = new Dogs.insert({barkSound: "ruff"}) 
Dogs.find(aDogID).bark(); // "ruff" 

Bonus: Se per qualsiasi motivo si desidera utilizzare un concetto simile a quello proposto da Andrew Ferk, basta usare la funzione _.defaults (oggetto, * defaults).

var defaults = { 
      barkSound: "ruff", 
      bark: function() { 
         console.log(this.barkSound); 
        } 
      } 

Dogs = new Meteor.Collection("dogs", 
     { 
      transform: function(object) { 
       return _.defaults(object, defaults); 
      } 
     }); 
+0

Questo sembra il modo giusto e ufficiale per farlo. Vado con questo. – the0ther

+0

Questa è una soluzione fantastica, grazie !!! Cambia completamente il mio codice meteorologico ora. Come mi sono perso nei documenti ??? –

+2

Post sull'argomento con altri esempi: http://www.okgrow.com/posts/2014/05/19/meteor-transform/ – Shwaydogg

2

Questa è una domanda relativamente vecchio, in termini di meteora, ma penso dburles:collection-helpers si inserisce il disegno di legge di quello che si voleva ottenere, mediante l'attuazione di ciò che Flavien Volken suggerito. Forse è utile per chiunque vaghi qui di recente.

+0

Grazie, apprezzo l'aggiornamento con nuove tecniche. Sto ancora usando minimongoid (https://atmospherejs.com/kaptron/minimongoid) che supporta dichiarazioni come '' 'has_one''' e' 'appartiene_to'''. – Samo

4

Astronomy è una nuova risposta a questa vecchia domanda di modelli Meteor. L'autore ha molte più funzioni pianificate che sono in lavorazione e il supporto di altri importanti autori di pacchetti di Meteor. L'unico lato negativo è forse è un po 'sanguinante.

L'astronomia è anche highly modularized, un primo esempio per la costruzione in uno stile impacchettato/modulare.

+0

Grazie per questo aggiornamento, sembra promettente! – Samo

0

Aggiunte alla risposta di @Flavien Volken è possibile passare argomenti al metodo che è stato aggiunto alla raccolta.

Car = new Mongo.Collection('car', { 
    transform: function(entry) { 
     entry.is_watched = function(userId) { 
      var is_watched = false; 
      if (entry.watchList) { 
       for (var i in entry.watchList) { 
        if (entry.watchList[i].userId == userId) { 
         is_watched = true; 
         break; 
        } 
       } 
      } 
      return is_watched; 
     }; 
     return entry; 
    } 
}); 

Nel modello (passando id utente collegato):

{{# if is_watched currentUser._id }} 
    Watched 
{{ else }} 
    Not watched 
{{/ if }} 
Problemi correlati