Подтвердить что ты не робот

Как вручную установить состояние объекта для очистки (сохранения) с использованием данных ember-data

Объяснение:

Я использую данные ember для моего проекта, и у меня есть вопрос, который вращается вокруг возможности загрязнения объекта, а затем устанавливает его состояние для очистки снова специально - без внесения изменений. Сценарий таков:

Скажем, что я получил объект через banana = App.Fruit.find('banana'); и в нем есть описание "Желтые фрукты!". Используя длинный опрос XHR (или WebSockets), я могу получить обновленную версию объекта из-за того, что другой пользователь изменил описание на "Вкусные желтые фрукты!". в любой момент времени после того, как я извлек исходный объект.

Тогда, что я хотел бы сделать, это обновить объект, чтобы отразить вновь полученные данные. Для этого я пробовал разные подходы:

  • Я пробовал звонить App.Store.load(App.Fruit, new_data);. Прежде всего, этот подход не работает, а во-вторых, это не совсем то, что я хочу. Я мог бы сделать незафиксированные изменения в самом объекте, и в этом случае было бы нежелательно просто отбрасывать их (предполагая, что вызов load() перезапишет их).

  • Я пробовал перебирать новые данные, вызывая .set() - так: banana.set('description', new_data.description); - чтобы обновить свойства объекта новыми данными (где применимо = не грязно). Это работает, но он оставляет объект в загрязненном состоянии.

Чтобы сделать объект чистым/обновленным снова - и не, адаптер адаптирует изменения! - Я взглянул на состояния, через которые проходит объект. Это (по крайней мере):

  • Шаг 1: Изначально объект находится в состоянии rootState.loaded.saved.
  • Шаг 2: Вызов .set() в свойстве подталкивает его в состояние rootState.loaded.updated.uncommitted.
  • Шаг 3: Вызов App.store.commit(); возвращает объект в состояние rootState.loaded.saved.

Поэтому я попытался вручную установить состояние объекта на saved после шага 2 следующим образом: banana.get('stateManager').goToState('saved');.

Однако это не работает. В следующий раз, когда магазин совершит по любой другой причине, этот маневр вызывает inFlightDirtyReasons - ошибка undefined.

Вопрос:

Мой вопрос: как я могу вручную изменить состояние загрязненного объекта обратно, чтобы снова очистить (сохранить)?

4b9b3361

Ответ 1

Глядя на данные ember, незафиксированное состояние имеет событие "cccan", которое, следовательно, устанавливает запись как загруженную .saved.

Это должно сделать трюк

record.get('stateManager').send('becameClean');  

Ответ 2

Решение для Ember Data 1.0.0-beta.7:

// changing to loaded.updated.inFlight, which has "didCommit" 
record.send('willCommit'); 
// clear array of changed (dirty) model attributes
record.set('_attributes', {});
// changing to loaded.saved (hooks didCommit event in "inFlight" state)
record.send('didCommit');

Я искал исходный код Ember-данных, и я обнаружил, что состояние загруженного состояния имеет функцию настройки, которая проверяет, является ли модель чистой, перед установкой состояния "сохранено". Если он не является чистым, он отклоняет запрос на изменение состояния и возвращает его на загруженный .updated.uncommitted.

Итак, вы должны очистить массив model._attributes, который сохраняет имена атрибутов, а Ember позволит вам изменить состояние вручную.

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

Ответ 4

Это обновление для решения @Kamil-j.

Для Ember Data 2.0, который я использую в настоящее время, я должен сделать следующее:

record._internalModel.send('willCommit'); 
record._internalModel._attributes = {};
record._internalModel.send('didCommit');

Ответ 5

Начиная с 1.0.0.rc6.2....

Это переместит модель в состояние модели, которая была сохранена.

record.get('stateManager').transitionTo('loaded.saved') 

Это переместит модель в состояние новой модели, которая не была выполнена. Подумайте о новой грязной модели.

record.get('stateManager').transitionTo('loaded.created.uncommitted')

Это переместит модель в состояние старой модели, которая была обновлена, подумайте о старой грязной модели:

record.get('stateManager').transitionTo('loaded.updated')

Ответ 6

По состоянию на ember-data 1.0.0-beta.12:

record.transitionTo('loaded.saved');

Кажется, что record.get('stateManager') больше не требуется.

Ответ 7

Вот что, похоже, работает для Ember Data 1.0.0-beta.10:

record.set('currentState.stateName', 'root.loaded.saved');
record.adapterWillCommit();
record.adapterDidCommit();
record.set('currentState.isDirty', false);

Не уверен, что все эти строки необходимы, но просто следуют за тем, что сделали другие до этого.

Ответ 8

Эмбер 2.9.1

record.set('currentState.isDirty', false);

Ответ 9

Похоже, что с новыми версиями все мелодированные здесь были сломаны.

Это работало для меня с ember-data 1.0.0.beta4:

record.adapterWillCommit();
record.adapterDidCommit();

Ответ 10

Другой метод, который работал у меня при использовании Ember Data 1.0.0-beta.18:

record.rollback()

Это отменило грязные атрибуты и вернуло запись в чистое состояние.

Похоже, что это было так устарело в пользу record.rollbackAttributes: http://emberjs.com/api/data/classes/DS.Model.html#method_rollbackAttributes

Ответ 11

Протестировано по данным Ember 2.9

pushedData - это способ, но кроме того, что "originalValues" также должен быть reset.

Ember.assign(record.data, record._internalModel._attributes);
Ember.assign(record._internalModel._data, record._internalModel._attributes);
record.send('pushedData');

Ответ 12

Я работаю над данными Ember 1.13, поэтому я использовал следующее решение (которое, похоже, представляет собой сочетание между предоставленным @Martin Malinda и другим @Serge):

// Ensure you have the changes inside the record
Object.assign(record.data, record._internalModel._attributes);
Object.assign(record._internalModel._data,record._internalModel._attributes);

// Using the DS.State you can first simulate the record is going to be saved
record.get('_internalModel').send('willCommit');

// Cleaning the prevous dirty attributes
record.get('_internalModel')._attributes = {};

// Mark the record as saved (root.loaded.created.uncommitted) even if it isn't for real
record.get('_internalModel').send('didCommit');

Таким образом, если мы вызовем еще один rollbackAttributes() для этой записи, если у нас будут некоторые грязные атрибуты, запись будет сброшена в это последнее состояние (вместо того, чтобы иметь исходные свойства), которое было именно тем, что я искал в моем случае использования.

Если у нас не будет грязных атрибутов, ничего не изменится, и мы сохраним последние атрибуты, установленные с помощью этого кода, без возврата к исходным. Надеюсь, это поможет.

Ответ 13

Проверено на Ember Data 3.8.0

Просто обновление для Мартина Малинды ответ:

// Not sure if these are necessary steps
// Ember.assign(record.data, record._internalModel._recordData._attributes);
// Ember.assign(record._internalModel._recordData._data, record._internalModel._recordData._attributes);

// Clear changed attributes list 
record._internalModel._recordData._attributes = {};

// Trigger transition to 'loaded.saved' state
record.send('pushedData');

В моем случае мне также нужно было переопределить метод сериализатора normalize.