Ответ 1
Глядя на данные ember, незафиксированное состояние имеет событие "cccan", которое, следовательно, устанавливает запись как загруженную .saved.
Это должно сделать трюк
record.get('stateManager').send('becameClean');
Я использую данные ember для моего проекта, и у меня есть вопрос, который вращается вокруг возможности загрязнения объекта, а затем устанавливает его состояние для очистки снова специально - без внесения изменений. Сценарий таков:
Скажем, что я получил объект через banana = App.Fruit.find('banana');
и в нем есть описание "Желтые фрукты!". Используя длинный опрос XHR (или WebSockets), я могу получить обновленную версию объекта из-за того, что другой пользователь изменил описание на "Вкусные желтые фрукты!". в любой момент времени после того, как я извлек исходный объект.
Тогда, что я хотел бы сделать, это обновить объект, чтобы отразить вновь полученные данные. Для этого я пробовал разные подходы:
Я пробовал звонить App.Store.load(App.Fruit, new_data);
. Прежде всего, этот подход не работает, а во-вторых, это не совсем то, что я хочу. Я мог бы сделать незафиксированные изменения в самом объекте, и в этом случае было бы нежелательно просто отбрасывать их (предполагая, что вызов load()
перезапишет их).
Я пробовал перебирать новые данные, вызывая .set()
- так: banana.set('description', new_data.description);
- чтобы обновить свойства объекта новыми данными (где применимо = не грязно). Это работает, но он оставляет объект в загрязненном состоянии.
Чтобы сделать объект чистым/обновленным снова - и не, адаптер адаптирует изменения! - Я взглянул на состояния, через которые проходит объект. Это (по крайней мере):
rootState.loaded.saved
..set()
в свойстве подталкивает его в состояние rootState.loaded.updated.uncommitted
.App.store.commit();
возвращает объект в состояние rootState.loaded.saved
.Поэтому я попытался вручную установить состояние объекта на saved
после шага 2 следующим образом: banana.get('stateManager').goToState('saved');
.
Однако это не работает. В следующий раз, когда магазин совершит по любой другой причине, этот маневр вызывает inFlightDirtyReasons - ошибка undefined.
Мой вопрос: как я могу вручную изменить состояние загрязненного объекта обратно, чтобы снова очистить (сохранить)?
Глядя на данные ember, незафиксированное состояние имеет событие "cccan", которое, следовательно, устанавливает запись как загруженную .saved.
Это должно сделать трюк
record.get('stateManager').send('becameClean');
Решение для 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 позволит вам изменить состояние вручную.
Я знаю, что это не очень хорошее решение, потому что необходимо установить частное свойство модели, но пока не найдено никаких других решений.
Решение для Ember Data 2.6.1
record.send('pushedData');
установить грязную запись как загруженную и сохраненную
Это обновление для решения @Kamil-j.
Для Ember Data 2.0, который я использую в настоящее время, я должен сделать следующее:
record._internalModel.send('willCommit');
record._internalModel._attributes = {};
record._internalModel.send('didCommit');
Начиная с 1.0.0.rc6.2....
Это переместит модель в состояние модели, которая была сохранена.
record.get('stateManager').transitionTo('loaded.saved')
Это переместит модель в состояние новой модели, которая не была выполнена. Подумайте о новой грязной модели.
record.get('stateManager').transitionTo('loaded.created.uncommitted')
Это переместит модель в состояние старой модели, которая была обновлена, подумайте о старой грязной модели:
record.get('stateManager').transitionTo('loaded.updated')
По состоянию на ember-data
1.0.0-beta.12:
record.transitionTo('loaded.saved');
Кажется, что record.get('stateManager')
больше не требуется.
Вот что, похоже, работает для Ember Data 1.0.0-beta.10:
record.set('currentState.stateName', 'root.loaded.saved');
record.adapterWillCommit();
record.adapterDidCommit();
record.set('currentState.isDirty', false);
Не уверен, что все эти строки необходимы, но просто следуют за тем, что сделали другие до этого.
Эмбер 2.9.1
record.set('currentState.isDirty', false);
Похоже, что с новыми версиями все мелодированные здесь были сломаны.
Это работало для меня с ember-data 1.0.0.beta4:
record.adapterWillCommit();
record.adapterDidCommit();
Другой метод, который работал у меня при использовании Ember Data 1.0.0-beta.18:
record.rollback()
Это отменило грязные атрибуты и вернуло запись в чистое состояние.
Похоже, что это было так устарело в пользу record.rollbackAttributes
: http://emberjs.com/api/data/classes/DS.Model.html#method_rollbackAttributes
Протестировано по данным Ember 2.9
pushedData - это способ, но кроме того, что "originalValues" также должен быть reset.
Ember.assign(record.data, record._internalModel._attributes);
Ember.assign(record._internalModel._data, record._internalModel._attributes);
record.send('pushedData');
Я работаю над данными 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()
для этой записи, если у нас будут некоторые грязные атрибуты, запись будет сброшена в это последнее состояние (вместо того, чтобы иметь исходные свойства), которое было именно тем, что я искал в моем случае использования.
Если у нас не будет грязных атрибутов, ничего не изменится, и мы сохраним последние атрибуты, установленные с помощью этого кода, без возврата к исходным. Надеюсь, это поможет.
Проверено на 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
.