ExtJS и сложные операции сохранения

ExtJS 4.1.0

Обновление 6/6/13:

Я разместил этот же вопрос на форумах Сенчи, где нетбыло много действий. Пост более или менее такой же, но я решил добавить сюда только для справки. Я все еще хочу услышать других членов сообщества вклад в то, что должно быть очень распространенным сценарием в приложении ExtJS!http://www.sencha.com/forum/showthread.php?265358-Complex-Model-Save-Decoupling-Data-and-Updating-Related-Stores

Обновление 16.07.13 (Заключение?)

Сообщение Сенчи вызвало очень мало дискуссий. Я решил перекладывать большую часть сложных операций сохранения на сервер приложений и лениво обновлять клиентские хранилища там, где это необходимо. Таким образом, я могу использовать свою собственную обертку базы данных, чтобы охватить все транзакции, связанные с одним сложным сохранением объекта домена, чтобы гарантировать атомарность. Если сохранить новыйOrder состоит из сохранения метаданных заказа, десяти новых экземпляровOrderContents и потенциально другую информацию (адреса, находящиеся в других таблицах, новый клиент, определенный во время создания заказа и т. д.), я бы скорее отправил полезную нагрузку на сервер приложений, чем создавал бы вульгарную сеть обратных вызовов в клиентском приложении. код. Данные, которые связаны один на один (например,Order hasOneAddress) обновляется вsuccess обратный вызовOrder.save() операция. Более сложные данные, такие какOrderс содержимым, лениво обрабатывается простым вызовом.contentStore.sync()Я чувствую, что это средство гарантировать атомарность без подавляющего числа обратных вызовов

Оригинальный контент

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

Возьмите, к примеру, сохранениеOrder объект, который состоит из метаданных, а такжеOrderContents части на заказ. Метаданные заканчиваются вOrder_Data таблица в базе данных, в то время как все содержимое в конечном итогеOrder_Contents таблица, где каждая строка связана с родительским заказом черезorder_id колонка.

На клиенте получение содержимого заказа довольно просто, без каких-либо ассоциаций:var contents = this.getContentsStore().query('order_id', 10).getRange(), Тем не менее, основным недостатком является то, чтоэто зависит от содержания записей, доступных вOrderContents Магазин ExtJS, что применимо, если бы я использовал ассоциации, НЕ возвращаемые сервером данных с "главный" объект.

Сохраняя заказ, я отправляю один запрос, который содержит заказ.s метаданные (например, дата, номер заказа, информация о поставщике и т. д.), а также массив содержимого. Эти фрагменты данных отбираются и сохраняются в соответствующих таблицах. Это имеет достаточно смысла для меня и работает хорошо.

Все хорошо, пока не вернется сохранение / обновление записей с сервера приложений. Так как запрос выполняется с помощью вызоваOrderObject.save()Нечего рассказыватьOrderContents хранить, что новые записи доступны. Это было бы обработано автоматически, если бы я вместо этого добавил записи в хранилище и позвонил.sync(), но я чувствую, что это усложняет процесс сохранения, и я бы просто предпочел справиться с этой развязкой на сервере приложений, не говоря уже о сохранении всего запроса.

Есть ли лучший способ решить эту проблему? Мое текущее решение заключается в следующем ...

var orderContentsStore = this.getOrderContentsStore();
MyOrderObject.save({
    success: function(rec, op){
        // New Content Records need to be added to the contents store!
        orderContentsStore.add(rec.get('contents')); // Array of OrderContent Records
        orderContentsStore.commitChanges(); // This is very important
    }
});

По телефонуcommitChanges() записи, добавленные в хранилище, считаются чистыми (не фантомными, не грязными) и, следовательно, больше не возвращаются хранилищемgetModifiedRecords() Способ; правильно, поскольку записи не должны передаваться на сервер приложений в случаеstore.sync()

Мне кажется, что такой подход немного неаккуратный / хакерский, но у меня нетЯ не нашел лучшего решения ...

Любой вклад / мысли с благодарностью!

 Mike17 июл. 2013 г., 14:09
К сожалению, это единственный способ сделать это. В качестве альтернативы, вы можете написать свой собственныйписатель» в магазинеС прокси и обрабатывать различные модели там, но это также было бы грязно.
 John Hall17 июл. 2013 г., 16:45
Спасибо за подтверждение моих убеждений, @Mike. Я'я собираюсь написать сообщение в блоге однажды, и яЯ отвечу на этот вопрос с информацией из указанного поста. Я действительно думал о реализации какого-то сумасшедшего расширения для Data Writer, но для достижения цели (сохранение store.load () здесь и там) я чувствую дополнительную сложность и время, необходимое для реализации простоне стоит моего времени.

Ответы на вопрос(1)

Решение Вопроса

Обновление 26.08.13 Я обнаружил, что связанные данные действительно обрабатываются Ext в обратном вызове create / update для модели 'с прокси, но обнаружил, что данные не былиt easy ... Смотрите мой пост здесь:ExtJS 4.1 - Возвращение связанных данных в ответе Model.Save ()

Ну, этоПрошло пару месяцев с того, что этот вопрос был открыт, и я чувствую, что волшебного решения этой проблемы не существует.

Мое решение заключается в следующем ...

При сохранении сложной модели (например, модель, которая будет или имеет несколькоhasMany ассоциации) спасаюродителя модель, которая включает все связанные данные (как свойство / поле в модели!), а затем добавляет (сохраненные) связанные данные в обратный вызов afterSave / afterUpdate.

Возьмите например мойPurchaseOrder модель, котораяhasMany Items а такжеhasOne Address, Обратите внимание, что соответствующие данные включены в модельs свойства, так как он не будет передан на сервер, если он существует только в модели 'Ассоциация магазинов.

console.log(PurchaseOrder.getData());
---
id: 0
order_num: "PO12345"
order_total: 100.95
customer_id: 1
order_address: Object
    id: 0
    ship_address_1: "123 Awesome Street"
    ship_address_2: "Suite B"
    ship_city: "Gnarlyville"
    ship_state: "Vermont"
    ship_zip: "05401"
    ...etc...
contents: Array[2]
    0: Object
        id: 0
        sku: "BR10831"
        name: "Super Cool Shiny Thing"
        quantity: 5
        sold_price: 84.23
    1: Object
        id: 0
        sku: "BR10311"
        name: "Moderately Fun Paddle Ball"
        quantity: 1
        sold_price: 1.39

я имеюModels создан дляPurchaseOrder.Content а такжеPurchaseOrder.AddressТем не менее, данные вPurchaseOrder это не пример этих моделей, а просто данные. Опять же, это для того, чтобы убедиться, что он правильно передается на сервер приложений.

Получив объект, подобный описанному выше, я отправляю его на сервер приложений через.save() следующее:

PurchaseOrder.save({
    scope: me,
    success: me.afterOrderSave,
    failure: function(rec,op){
        console.error('Error saving Purchase Order', op);
    }
});

afterOrderSave: function(record, operation){
    var me = this;
    switch(operation.action){
        case 'create':
            /** 
              * Add the records to the appropriate stores.
              * Since these records (from the server) have an id,
              * they will not be marked as dirty nor as phantoms 
              */
            var savedRecord = operation.getResultSet().records[0];  // has associated!
            me.getOrderStore().add(savedRecord);
            me.getOrderContentStore().add(savedRecord.getContents()); //association!
            me.getOrderAddressStore().add(savedRecord.getAddress()); // association!
            break;

        case 'update':
            // Locate and update records with response from server
            break;
    }
}

Мой сервер приложений получаетPurchaseOrder и обрабатывает сохранение данных соответственно. Я не буду вдаваться в подробности, так как этот процесс во многом зависит от вашей собственной реализации. Моя прикладная среда слабо основана на Zend 1.11 (главным образом используяZend_Db).

Я чувствую, что это лучший подход по следующим причинам:

Нет грязной строки различных обратных вызовов model.save () на клиентеТолько один запрос, которым очень легко управлятьАтомность легко обрабатывается на сервере приложенийМеньше поездок туда и обратно = меньше потенциальных точек беспокойстваЕсли ты'действительно ленив,success метод обратного вызова может простоreload магазины.

Я оставлю этот ответ на некоторое время, чтобы стимулировать обсуждение.

Спасибо за прочтение!

 Mike24 июл. 2013 г., 14:50
Я думаю, что это, вероятно, один из самых чистых способов пойти. +1
 John Hall24 июл. 2013 г., 15:14
@ Майк Спасибо за продолжение, ценю это!

Ваш ответ на вопрос