2015-10-06 11 views
5

In Ember, diciamo che ho un oggetto chiamato FoodStuff che ha alcune proprietà:proprietà richieste (args costruttore) in casi Ember.Object

export default Ember.Object.extend({ 
    name: null,  // REQUIRED: 'Slice of Apple Pie' 
    calories: null, // OPTIONAL: int: eg. 250 
    category: null, // REQUIRED: 'Pastry' 
    rating: null // OPTIONAL: int: 1-5 
}); 

Come posso scrivere un 'costruttore' in Ember, richiedendo che le proprietà 'nome' e 'categoria' siano fornite al momento dell'istanziazione?

angolare sembra avvicinarsi a questo con la sintassi abbastanza semplice:

.factory('User', function (Organisation) { 

    /** 
    * Constructor, with class name 
    */ 
    function User(firstName, lastName, role, organisation) { 
    // Public properties, assigned to the instance ('this') 
    this.firstName = firstName; 
    ... 

Angular model objects with JavaScript classes

fa Ember hanno qualcosa di simile? Attualmente tutte le mie classi sono viste in alto, con un gruppo di proprietà inizialmente nulle che potrebbe essere impostato o meno correttamente dal chiamante. Al momento della compilazione (sto usando ember-cli) vorrei che le modifiche ai requisiti del costruttore venissero catturate a valle dalla fase ember build con JSHint.

risposta

2

Per quanto ne so, non esiste un modo nativo per farlo in Ember. Ma non c'è niente di impossibile! Puoi modificare un po 'Ember per gestire il caso. Basta aggiungere un inizializzatore:

/initializers/extend-ember.js:

import Ember from 'ember'; 

export function initialize() { 

    Ember.Object.reopen({ 

    /** 
    * @prop {Array} - array of required properties 
    */ 
    requiredAttrs: [], 

    /** 
    * Validates existance of required properties 
    * 
    * @param {String} attr - attribute name 
    * @param {*} value - value of the property 
    * @throws {Error} in case when required property is not set 
    */ 
    _validateExistance(attr, value) { 
     if (this.requiredAttrs.contains(attr) && typeof value === "undefined") { 
     throw new Error("Attribute " + attr + " can't be empty!"); 
     } 
    }, 

    /** 
    * Sets value of a property and validates existance of required properties 
    * 
    * @override 
    */ 
    set(key, value) { 
     this._validateExistance(key, value); 
     return this._super(key, value); 
    } 

    }); 

    Ember.Object.reopenClass({ 

    /** 
    * Creates object instance and validates existance of required properties 
    * 
    * @override 
    */ 
    create(attrs) { 
     let obj = this._super(attrs); 
     if (attrs) { 
     obj.requiredAttrs.forEach((key) => { 
      obj._validateExistance(key, attrs[key]); 
     }); 
     } 
     return obj; 
    } 

    }); 

} 

export default { 
    name: 'extend-ember', 
    initialize: initialize 
}; 

quindi è possibile utilizzare requiredAttrs proprietà su qualsiasi classe di definire quali proprietà sono necessari. Genera un'eccezione se si tenta di creare un'istanza con proprietà obbligatorie vuote o se si tenta di impostare un valore vuoto nella proprietà richiesta.

let MyModel = Ember.Object.extend({ 
    prop1: null, 
    prop2: null, 
    requiredAttrs: ['prop2'] 
}); 

let ChildModel = MyModel.extend({ 
    prop3: null, 
    requiredAttrs: ['prop2', 'prop3'] 
}); 

// throws exception 
let obj1 = MyModel.create({ 
    prop1: 'val1' 
}); 

// no exception 
let obj2 = MyModel.create({ 
    prop2: 'val2' 
}); 

// throws exception 
obj2.set('prop2', undefined); 

// throws exception 
let obj3 = ChildModel.create({ 
    prop3: 'val3' 
}); 

// no exception 
let obj4 = ChildModel.create({ 
    prop2: 'val2', 
    prop3: 'val3' 
}); 

Si lavorerà anche sulla DS.Model e altri enti Ember fuori dalla scatola, dal momento che tutti si estendono Ember.Object.

+0

La soluzione funziona per te? –

+0

Mentre è un controllo di runtime, e stavo cercando un controllo build/JSHint-time, questa sembra essere la cosa più vicina. Grazie. –

1

Per avere instantiation tempo controlli (runtime), si desidera sovrascrivere il metodo init:

init() { 
    this._super(); 
    Ember.assert('Name cannot be empty', name); 
    // ... 
} 

per loro di essere catturati in accumulo tempo, non sono sicuro di un buon modo per Fai quello. È possibile utilizzare un qualche tipo di strumento per aggiungere la tipizzazione statica a Javascript (Typescript e Flow vengono in mente), che potrebbe essere in grado di forzare tali proprietà durante l'istanziazione di tali oggetti. Potresti anche scrivere uno strumento personalizzato (come un plugin ESLint) per verificarlo, ma probabilmente è più difficile di quello che vale. Probabilmente stai meglio con una soluzione runtime e una copertura di test decente.


Ecco un esempio di avere il proprio metodo create().

SomeClass.reopenClass({ 
    create(name, category, calories = null, rating = null) { 
     // Validate your properties 
     Ember.assert('Name cannot be empty', name); 
     // ... 

     // Create the object 
     var obj = this._super({ name, category, calories, rating }); 

     // Do any other setup/validation 

     // Return the object 
     return obj; 
    } 
}); 
+0

Speravo che ci fosse un modo per rimuovere o nascondere la funzione 'create()', e invece richiedere alle sottoclassi di scriverne di proprie, decidendo quali parametri di init sarebbero richiesti. –

+0

Puoi farlo se vuoi, ma tieni presente che alla fine dovrai chiamare 'create()' affinché Ember possa impostare tutto correttamente. Aggiornerò la mia risposta con un esempio – GJK

Problemi correlati