AngularFire: как обновить $firebaseArray, расширив службу и используя закрытый метод $$updated

У меня есть два отдельных списка сообщений и авторов в моей базе данных, каждое сообщение содержит authorId для ссылки на соответствующего автора.

Следующий метод помогает мне получить весь список сообщений, систематически включая имя автора для каждого сообщения:

app.factory('NormalizedPosts', function($firebaseArray, FirebaseFactory) {
    var PostsWithAuthors = $firebaseArray.$extend({

        // override $$added to include author name
        $$added: function(snap) {
            var record = $firebaseArray.prototype.$$added.call(this, snap);

            FirebaseFactory.$getAuthorId( record.authorId ).$loaded(function( authorData ) {
                record.authorData = authorData;
            });

            return record;
        },

        // ????????
        $$updated: function(snap) { 

            var rec = $firebaseArray.prototype.$$updated.call(this, snap); 
            var updatedRecord = this.$getRecord(snap.key()); 

            FirebaseFactory.$getAuthorId( updatedRecord.authorId )
            .$loaded(function( authorData ) { 
                rec.authorData = authorData; 
            }); 

        return rec; 

        }

    });

    return PostsWithAuthors;
});

PS: FirebaseFactory — это просто оболочка для методов firebase.

тогда я звоню

var list = new NormalizedPosts ( new Firebase(FBURL).child("posts") ); 

в моем контроллере, чтобы получить полный список. Это прекрасно работает.

Я ломаю голову над тем, что должно войти в метод $$updated: когда добавляется новая запись, список обновляется, как и ожидалось (через метод $$added). Но когда в данных поста происходят изменения (например, заголовок поста), мой список не обновляется, так как в настоящее время я возвращаю false в методе $$updated.

Вопрос: Что должно быть в методе $$updated, чтобы при изменении данных поста мой список обновлялся соответствующим образом (и в дальнейшем возвращал имя автора!). Спасибо


person Stephane B.    schedule 23.07.2016    source источник


Ответы (1)


Я думаю, вы проходите слишком много циклов, чтобы сделать что-то простое.

Если имя автора является «частью» статьи, ее следует сохранить:

{
    "articles": {
        "firebase-uniq-id-1": {
            "title": "My Writing Process",
            "published": "2016-01-01",
            "author": {
                "firebase-uniq-id-2": "Ernest Hemingway"
            }
        }
    },
    "authors": {
        "firebase-uniq-id-2": {
            "name": "Ernest Hemingway",
            "born": "1899-07-21",
            "whatever": "Some Data"
        }
    }
}

Когда вы захотите показать другие сведения об авторе, извлеките его.

Изменить: если вы все еще хотите использовать опцию расширения, я считаю, что единственное, чего вам не хватает, это расширение updateRecord с помощью rec:

FirebaseFactory.$getAuthorId( updatedRecord.authorId )
    .$loaded(function( authorData ) { 
        updatedRecord.authorData = authorData; 
        angular.extend(updatedRecord, snap.val());
    });

Также в $$updated нужно возвращать логическое выражение, изменилась запись или нет, а не сама запись.

Имейте в виду, что если вы пойдете по этому пути, вы не должны использовать метод $save() по умолчанию для $firebaseArray, поскольку он также сохранит полные данные автора.

person idan    schedule 26.07.2016
comment
Спасибо Идан. Случай, который я описал выше, действительно является простым случаем, и ваш подход хорошо работает для получения имени автора. На практике мне нужно получить все виды данных (издательская компания, данные о продажах и т. д.) в одном и том же запросе. Поэтому не могли бы вы предложить систематически дублировать необходимые данные в узле статей для всех данных, которые мне нужны (с тем же подход, который вы использовали в своем примере) Или вы воспользуетесь моим подходом для расширения службы, и в этом случае, согласно моему первоначальному вопросу, как я могу убедиться, что данные будут обновляться через расширенную службу? - person Stephane B.; 26.07.2016
comment
Это зависит от того, насколько богаты данные. Насколько я знаю, это подход для баз данных на основе JSON. У вас есть индекс и выбранные данные в качестве значения индекса. Если вам все еще нужно расширение, я думаю, что в документации AngularFire есть несколько хороших примеров, которые могут помочь. - person idan; 26.07.2016
comment
Спасибо Идан. Боюсь, нет примера с документами AngularFire. И единственное подходящее, что я нашел, не решает проблему обновления $$, с которой я сталкиваюсь: Катовульф/f78d4a224c06a643ddfa - person Stephane B.; 26.07.2016
comment
А как насчет $$updated: function(snap) { // this is the $firebaseArray instance so you can use it instead of $firebaseArray.prototype var updatedRecord = this.$getRecord(snap.key()); FirebaseFactory.$getAuthorId( updatedRecord.authorId ).$loaded(function( authorData ) { updatedRecord.authorData = authorData; }); // You could return false if it's not modified, just returning this for simplicity return !!updatedRecord; } - person idan; 27.07.2016
comment
Идан спасибо за продолжение; это делает свое дело, и возвращается обновленная запись с автором; однако проблема заключается в том, что 'var updatedRecord = this.$getRecord(snap.key())' извлекает старые данные, поэтому, если что-то обновляется в самой записи, например. заголовок статьи, он не возвращает новый заголовок; Есть идеи? - person Stephane B.; 30.07.2016
comment
Хорошо, так что просто вызовите супер $$updated, как вы сделали для метода $$added, или просто обновите себя, используя snap.val() в качестве новых данных. - person idan; 30.07.2016
comment
Я не совсем понимаю ваш вариант 2) // что касается варианта 1), мы вернулись к моему первоначальному вопросу: $$updated: function(snap) { var rec = $firebaseArray.prototype.$$updated.call( это, оснастка); var updatedRecord = this.$getRecord(snap.key()); FirebaseFactory.$getAuthorId( updatedRecord.authorId ).$loaded(function( authorData ) { rec.authorData = authorData; }); return rec } // обновляет заголовок статьи, если есть изменения, но не добавляет authorData. Есть идеи? - person Stephane B.; 30.07.2016
comment
обратите внимание, что я обновляю rec в своем предложении, поскольку использую метод super $$updated; также обратите внимание, что я вызываю var rec = $firebaseArray.prototype.$$updated.call(this, snap), а не var rec = $firebaseObject.prototype.$$updated.call(this, snap) при расширении $firebaseArray (хотя я не нашел ни одного примера, который делает именно это) - person Stephane B.; 30.07.2016
comment
Здесь становится все труднее понять полную картину. Можете ли вы обновить код в своем вопросе тем, что у вас есть для $$updated? - person idan; 30.07.2016
comment
Идан, не совсем так, как updatedRecord все еще извлекает данные из существующего $firebaseArray, поэтому, если что-то там обновляется (например, заголовок статьи), выходные данные не будут отражать изменение. При этом ваша идея/комментарии помогли мне решить эту проблему - см. мой ответ ниже - так что большое спасибо за вашу помощь в этом! - person Stephane B.; 31.07.2016
comment
Рад помочь :) снова отредактировал, потому что я все еще верю, что у вас уже есть обновленная сущность в snap.val(), так что это избавляет вас от ожидания одного из $loaded() - person idan; 31.07.2016