Skip to content

Commit

Permalink
Fix models in store after batchUpdate
Browse files Browse the repository at this point in the history
  • Loading branch information
DubrovinPavel committed Nov 1, 2023
1 parent 2c03169 commit 3ae5255
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 24 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Change Log

## [Unreleased]
### Added
- Projections parameter for batchUpdate.

### Fixed
- Update model in store after batchUpdate.

## [3.10.0] - 2023-08-22
### Changed
Expand Down
58 changes: 37 additions & 21 deletions addon/adapters/odata.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,9 +410,10 @@ export default DS.RESTAdapter.extend({
@method batchUpdate
@param {DS.Store} store The store.
@param {DS.Model[]|DS.Model} models Is array of models or single model for batch update.
@param {Object} getProjections Optional projections for updated models.
@return {Promise} A promise that fulfilled with an array of models in the new state.
*/
batchUpdate(store, models) {
batchUpdate(store, models, getProjections = {}) {
if (isEmpty(models)) {
return resolve(models);
}
Expand Down Expand Up @@ -485,7 +486,8 @@ export default DS.RESTAdapter.extend({

// Don't need to send any data for deleting.
if (modelDirtyType !== 'deleted') {
const serializer = store.serializerFor(snapshot.type.modelName);
const modelName = snapshot.type.modelName;
const serializer = store.serializerFor(modelName);
const data = {};
serializer.serializeIntoHash(data, snapshot.type, snapshot);
requestBody += JSON.stringify(data) + '\r\n';
Expand All @@ -495,27 +497,39 @@ export default DS.RESTAdapter.extend({
getQuery += 'Content-Type: application/http\r\n';
getQuery += 'Content-Transfer-Encoding: binary\r\n';

const relationships = [];
model.eachRelationship((name) => {
// If attr serializable value hadn't been set up, it'll be { serialize: 'id' } by default from DS.EmbeddedRecordsMixin.
let attrSerializeVal =
serializer && serializer.attrs && serializer.attrs[name] && serializer.attrs[name].serialize;

if (attrSerializeVal !== false) {
relationships.push(`${name}.id`);
const getUrl = this._buildURL(modelName, model.get('id'));

const projection = get(getProjections, modelName);
if (isNone(projection)) {
const relationships = [];
model.eachRelationship((name) => {
// If attr serializable value hadn't been set up, it'll be { serialize: 'id' } by default from DS.EmbeddedRecordsMixin.
let attrSerializeVal =
serializer && serializer.attrs && serializer.attrs[name] && serializer.attrs[name].serialize;

if (attrSerializeVal !== false) {
relationships.push(`${name}.id`);
}
});

let expand;
if (relationships.length) {
const query = new Builder(store, modelName).select(relationships.join(',')).build();
const queryAdapter = new ODataQueryAdapter(getUrl, store);
expand = queryAdapter.getODataQuery(query).$expand;
}
});

const getUrl = this._buildURL(snapshot.type.modelName, model.get('id'));

let expand;
if (relationships.length) {
const query = new Builder(store, snapshot.type.modelName).select(relationships.join(',')).build();
getQuery += '\r\nGET ' + getUrl + (expand ? '?$expand=' + expand : '') + ' HTTP/1.1\r\n';
} else {
let query = new Builder(store, modelName);
query = isArray(projection) ? query.select(projection.join(',')) : query.selectByProjection(projection);
query = query.build();
const queryAdapter = new ODataQueryAdapter(getUrl, store);
expand = queryAdapter.getODataQuery(query).$expand;
const fullUrl = queryAdapter.getODataFullUrl(query);

getQuery += '\r\nGET ' + fullUrl + ' HTTP/1.1\r\n';
}

getQuery += '\r\nGET ' + getUrl + (expand ? '?$expand=' + expand : '') + ' HTTP/1.1\r\n';
getQuery += 'Content-Type: application/json;type=entry\r\n';
getQuery += 'Prefer: return=representation\r\n';
getQueries.push(getQuery);
Expand Down Expand Up @@ -566,11 +580,13 @@ export default DS.RESTAdapter.extend({
} else if (modelDirtyType === 'created' || modelDirtyType === 'updated' || model.hasChangedBelongsTo()) {
const { response } = getResponses.shift();
if (this.isSuccess(response.meta.status)) {
const internalModel = model._internalModel;
internalModel.adapterWillCommit();
internalModel.flushChangedAttributes();
const modelName = model.constructor.modelName;
const payload = { [modelName]: response.body };
run(() => {
store.pushPayload(modelName, payload);
model.rollbackAttributes(); // forced adjustment of model state
const normalized = store.normalize(modelName, response.body);
store.didSaveRecord(internalModel, normalized);
});
} else {
errors.push(new DS.AdapterError(response.body));
Expand Down
2 changes: 1 addition & 1 deletion addon/stores/base-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ export default DS.Store.extend({
@return {Promise} A promise that fulfilled with an array of models in the new state.
*/
batchUpdate() {
return this._callSuperMethod('batchUpdate', 1, arguments);
return this._callSuperMethod('batchUpdate', 2, arguments);
},

/**
Expand Down
5 changes: 3 additions & 2 deletions addon/stores/online-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ export default DS.Store.extend({
@method batchUpdate
@param {DS.Model[]|DS.Model} models Is array of models or single model for batch update.
@param {Object} getProjections Optional projections for updated models.
@return {Promise} A promise that fulfilled with an array of models in the new state.
*/
batchUpdate(models) {
return this.adapterFor('application').batchUpdate(this, models);
batchUpdate(models, getProjections) {
return this.adapterFor('application').batchUpdate(this, models, getProjections);
},

/**
Expand Down

0 comments on commit 3ae5255

Please sign in to comment.