2016-02-28 8 views
9

Chciałbym, aby baffle.where({id: 1}).fetch() zawsze otrzymywał atrybut typeName jako część modelu baffle, bez pobierania go z baffleType jawnie za każdym razem.Zawsze pobieraj z pokrewnych modeli w Bookshelf.js

następujące prace dla mnie, ale wydaje się, że withRelated załaduje stosunki jeśli baffle model jest pobierany bezpośrednio, a nie przez zależność:

let baffle = bookshelf.Model.extend({ 
    constructor: function() { 
     bookshelf.Model.apply(this, arguments); 

     this.on('fetching', function(model, attrs, options) { 
      options.withRelated = options.withRelated || []; 
      options.withRelated.push('type');   
     }); 
    }, 

    virtuals: { 
     typeName: { 
      get: function() { 
       return this.related('type').attributes.typeName; 
      } 
     } 
    }, 
    type: function() { 
     return this.belongsTo(baffleType, 'type_id'); 
    } 
}); 

let baffleType = bookshelf.Model.extend({}); 

Co to jest właściwy sposób to zrobić?

Odpowiedz

3

To pytanie jest bardzo stare, ale mimo to odpowiadam.

Rozwiązałem to, dodając nową funkcję, fetchFull, która utrzymuje wszystko w porządku.

let MyBaseModel = bookshelf.Model.extend({ 
    fetchFull: function() { 
    let args; 
    if (this.constructor.withRelated) { 
     args = {withRelated: this.constructor.withRelated}; 
    } 
    return this.fetch(args); 
    }, 
}; 

let MyModel = MyBaseModel.extend({ 
    tableName: 'whatever', 
    }, { 
    withRelated: [ 
     'relation1', 
     'relation1.related2' 
    ] 
    } 
); 

Wtedy gdy jesteś zapytań, można nazwać Model.fetchFull() załadować wszystko, lub w przypadkach, w których nie chcą podjąć się hitem wydajności, nadal można odwoływać się do Model.fetch().

+0

Dzięki, nigdy nie jest za późno. – estus

7

Problem na repo wiąże się z wydarzeniem Fetched, jednak zdarzenie Fetching działa dobrze (v0.9.2).

Więc na przykład jeśli masz 3rd modelu podobnego

var Test = Bookshelf.model.extend({ 
    tableName : 'test', 
    baffleField : function(){ 
     return this.belongsTo(baffle) 
    } 
}) 

a następnie wykonaj Test.forge().fetch({ withRelated : ['baffleField']}), fetching wydarzenie na przegrody będzie ogień. Jednak ORM nie będzie zawierała type (sub Powiązany model), chyba że wyraźnie powiedzieć, aby to uczynić przez

Test.forge().fetch({ withRelated : ['baffleField.type']}) 

jednak bym try to avoid to jeśli to czyni N Query dla N records.

UPDATE 1

Rozmawiałem o tej samej rzeczy, które robili na fetching imprezy jak

fetch: function fetch(options) { 
    var options = options || {} 
    options.withRelated = options.withRelated || []; 
    options.withRelated.push('type');  
    // Fetch uses all set attributes. 
    return this._doFetch(this.attributes, options); 
} 

w model.extend. Jednak, jak widać, może to się nie udać w przypadku zmian version.

+0

Dobra uwaga na temat "pobierania", dzięki. Tak więc modyfikuję opcję 'options.withRelated' jako jedyną opcję, jeśli chcę zachować logikę biznesową DRY i pomijać' {withRelated: ...} 'część we wszystkich wywołaniach' fetch() '? Wydajność nie jest krytyczna w tej części aplikacji. – estus

+0

@estus Myślę, że tak. Jednak używam sequelize na jakiś czas, więc nie mogę być tego pewien. Innym sposobem robienia tego samego jest "przesłonięcie" (nie jest dobrym słowem dla JS) metody pobierania w '' 'model.extend'''. Jednak praca z zdarzeniem '' 'pobieranie' '' jest raczej sposobem na zrobienie tego na półce. Przesłanianie metody jest bardziej czystsze, ale może się nie udać w przypadku aktualizacji/obniżenia wersji. – Satyajeet

+0

Wygląda na to, że 'fetching' jest wyzwalane, ale żadne relacje zagnieżdżone nie są ładowane, gdy 'przegrody' są ładowane jako relacje, więc' fetching 'powinno być określone w każdym modelu macierzystym. Czy mógłbyś dodać przykład zastępowania 'pobierania '? Powinien to być coś w stylu 'fetch: function (... args) {return bookshelf.Model.prototype.fetch.bind (this) (... args)}? – estus

Powiązane problemy