Skip to content

Commit 3ba6269

Browse files
authored
Rework DELETE method of Custom Object
Update eslint; Add DELETE CO by criteria; Normalize an answer on DELETE CO for any types;
1 parent 33ed72e commit 3ba6269

File tree

4 files changed

+45619
-52
lines changed

4 files changed

+45619
-52
lines changed

.eslintrc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
"extends": "eslint:recommended",
33
"env": {
44
"browser": true,
5-
"node": true
5+
"node": true,
6+
"es6": true,
7+
"jasmine": true
68
},
79
"globals": {
810
"QB": true,
@@ -19,4 +21,4 @@
1921
"no-mixed-spaces-and-tabs": 1,
2022
"no-extra-boolean-cast": 1
2123
}
22-
}
24+
}

quickblox.min.js

Lines changed: 45413 additions & 1 deletion
Large diffs are not rendered by default.

spec/QB-DataSpec.js

Lines changed: 84 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,28 +80,99 @@ describe('Custom Objects API', function() {
8080
}
8181
});
8282
}, REST_REQUESTS_TIMEOUT);
83+
});
8384

84-
it('can delete custom object', function(done){
85-
QB.data.create('cars', {make: 'BMW', model: 'M5', value: 100, damaged: true}, function(err, result) {
86-
if (err) {
87-
done.fail('Create custom object error: ' + JSON.stringify(err));
88-
} else {
89-
QB.data.delete('cars', result._id, function(err, res) {
90-
if (err) {
91-
done.fail("Create delete object error: " + JSON.stringify(err));
85+
describe('Delete custom object', function() {
86+
const className = 'cars';
87+
88+
function createCustomObject(className, params) {
89+
const defaultCarParams = {
90+
make: 'BMW',
91+
model: 'M5',
92+
value: 100,
93+
damaged: true
94+
};
95+
96+
const carParams = Object.assign(defaultCarParams, params);
97+
98+
return new Promise((resolve, reject) => {
99+
QB.data.create(className, carParams, function(error, result) {
100+
if (error) {
101+
reject(error);
102+
} else {
103+
resolve(result);
104+
}
105+
});
106+
});
107+
}
108+
109+
it('by ID', function(done) {
110+
createCustomObject(className, {}).then((car) => {
111+
QB.data.delete(className, car._id, function(error, responce) {
112+
if (error) {
113+
done.fail("Create delete object error: " + JSON.stringify(error));
114+
} else {
115+
expect(responce).not.toBeNull();
116+
expect(responce.deleted[0]).toEqual(car._id);
117+
118+
done();
119+
}
120+
});
121+
});
122+
}, REST_REQUESTS_TIMEOUT);
123+
124+
it('by IDs', function(done) {
125+
const promiseCreateCar1 = createCustomObject(className, {});
126+
const promiseCreateCar2 = createCustomObject(className, {});
127+
const promiseCreateCar3 = createCustomObject(className, {});
128+
129+
const promisesArray = [promiseCreateCar1, promiseCreateCar2, promiseCreateCar3];
130+
131+
Promise.all(promisesArray).then(function(cars) {
132+
const ids = cars.map(car => car._id);
133+
134+
QB.data.delete(className, ids, function(error, res) {
135+
if (error) {
136+
done.fail("Create delete object error: " + JSON.stringify(error));
137+
} else {
138+
expect(res).not.toBeNull();
139+
// Need sort arrays before compare
140+
// cause jasmine to compare one by one item
141+
expect(res.deleted.sort()).toEqual(ids.sort());
142+
143+
done();
144+
}
145+
});
146+
});
147+
}, REST_REQUESTS_TIMEOUT * 3);
148+
149+
it('by criteria', function(done) {
150+
const criteria = {
151+
'value': {
152+
'gt': 100
153+
}
154+
};
155+
156+
const promiseCreateCar1 = createCustomObject(className, {value: 150});
157+
const promiseCreateCar2 = createCustomObject(className, {value: 150});
158+
const promiseCreateCar3 = createCustomObject(className, {value: 150});
159+
160+
Promise.all([promiseCreateCar1, promiseCreateCar2, promiseCreateCar3])
161+
.then(function(cars) {
162+
QB.data.delete(className, criteria, function(error, res) {
163+
if (error) {
164+
done.fail("Create delete object error: " + JSON.stringify(error));
92165
} else {
93166
expect(res).not.toBeNull();
94-
expect(res).toBe(true);
167+
expect(res.deletedCount).toEqual(cars.length);
95168

96169
done();
97170
}
98171
});
99-
}
100-
});
101-
}, REST_REQUESTS_TIMEOUT);
172+
});
173+
}, REST_REQUESTS_TIMEOUT * 3);
102174
});
103175

104-
105176
describe('Custom Objects with files', function() {
106177
var paramsFile,
107178
paramsFor;
@@ -204,9 +275,7 @@ describe('Custom Objects API', function() {
204275

205276
});
206277

207-
208278
describe('Some more complex searching', function() {
209-
210279
it('can find instances of cars with a value over 50 (value: 100)', function(done){
211280
var filter = {
212281
'value': {
@@ -249,5 +318,4 @@ describe('Custom Objects API', function() {
249318
});
250319
}, REST_REQUESTS_TIMEOUT);
251320
});
252-
253321
});

src/modules/qbData.js

Lines changed: 118 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,45 @@
11
'use strict';
22

3-
/*
4-
* QuickBlox JavaScript SDK
5-
*
6-
* Custom Objects module
7-
*
8-
*/
9-
10-
var config = require('../qbConfig'),
11-
Utils = require('../qbUtils');
12-
13-
// For server-side applications through using npm package 'quickblox' you should include the following lines
14-
var isBrowser = typeof window !== 'undefined';
3+
const config = require('../qbConfig');
4+
const Utils = require('../qbUtils');
155

166
/**
17-
* Custom Objects
7+
* Custom Objects Module
188
* @namespace QB.data
199
**/
2010
function DataProxy(service){
2111
this.service = service;
2212
}
2313

2414
DataProxy.prototype = {
25-
2615
/**
2716
* Create new custom object ({@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Create_object read more})
17+
*
2818
* @memberof QB.data
19+
*
2920
* @param {string} className - A class name to which a new object belongs
3021
* @param {object} data - Object of parameters (custom fields' names and their values)
3122
* @param {createDataCallback} callback - The createDataCallback function
23+
*
3224
* @example
33-
* QB.data.create('GameOfThrones', {
25+
* const data = {
3426
* 'name': 'John',
3527
* 'age':'20',
3628
* 'family': [
3729
* 'Stark',
3830
* 'Targaryen'
3931
* ]
40-
* }, function(error, response) {
32+
* };
33+
*
34+
* function createdDataCallback(error, response) {
4135
* if (error) {
4236
* console.log(error);
4337
* } else {
4438
* console.log(response);
4539
* }
46-
* });
40+
* }
41+
*
42+
* QB.data.create('GameOfThrones', data, createdDataCallback);
4743
*/
4844
create: function(className, data, callback) {
4945
/**
@@ -71,7 +67,9 @@ DataProxy.prototype = {
7167

7268
/**
7369
* Search for records of particular class ({@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Retrieve_objects read more})
70+
*
7471
* @memberof QB.data
72+
*
7573
* @param {string} className - A class name to which a new record belongs
7674
* @param {(object|string[])} filters - Search records with field which contains exactly specified value or by array of records' ids to retrieve
7775
* @param {number} [filters.skip=0] - Skip N records in search results. Useful for pagination. Default (if not specified) - 0
@@ -122,7 +120,7 @@ DataProxy.prototype = {
122120
},
123121

124122
/**
125-
* Update record by ID of particular class ({@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Retrieve_objects read more})
123+
* Update record by ID of particular class. ({@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Retrieve_objects Read more})
126124
* @memberof QB.data
127125
* @param {string} className - A class name of record
128126
* @param {object} data - Object of parameters
@@ -165,27 +163,114 @@ DataProxy.prototype = {
165163
},
166164

167165
/**
168-
* Delete record by ID ({@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Delete_objects_by_IDs or records by ids}) of particular class ({@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Delete_object read more})
166+
* Delete record / records by ID, IDs or criteria (filters) of particular class. <br />
167+
* Check out {@link https://docsdev.quickblox.com/rest_api/CustomObjects_API.html#Delete_object official documentaion} to get detailed information.
168+
*
169169
* @memberof QB.data
170-
* @param {string} className - A class name of record (records)
171-
* @param {(string|array)} id - An ID of record (or an array of records' ids) to delete
172-
* @param {deleteDataByIdsCallback} callback - The deleteDataByIdsCallback function
170+
*
171+
* @param {string} className - A class name of record
172+
* @param {(string|array|object)} requestedData - An ID of record or an array of record's ids or object of criteria rules to delete
173+
* @param {deletedDataCallback} callback - The deletedDataCallback function
174+
*
175+
* @example
176+
* const className = 'Movie';
177+
*
178+
* function deletedMovie(error, responce) {
179+
* if(error) {
180+
* throw new Error(error.toString());
181+
* } else {
182+
* console.log(`Deleted movies with ids: ${responce.deleted.toString()}`);
183+
* }
184+
* }
185+
*
186+
* // By ID, must be string
187+
* const id = '502f7c4036c9ae2163000002';
188+
* QB.data.delete(className, id, deletedMovie);
189+
*
190+
* // By IDs, must be array
191+
* const ids = ['502f7c4036c9ae2163000002', '502f7c4036c9ae2163000003'];
192+
* QB.data.delete(className, ids, deletedMovie);
193+
*
194+
* const criteria = { 'price': { 'gt': 100 };
195+
* function deletedMoviesByCriteria(error, responce) {
196+
* if(error) {
197+
* throw new Error(error.toString());
198+
* } else {
199+
* // Note! Deleted by creteria doesn't return ids of deleted objects
200+
* console.log(`Deleted ${responce.deletedCount} movies`);
201+
* }
202+
* }
203+
* QB.data.delete(className, criteria, deletedMoviesByCriteria);
204+
*
205+
*
173206
*/
174-
delete: function(className, id, callback) {
207+
delete: function(className, requestedData, callback) {
175208
/**
176-
* Callback for QB.data.delete(className, id, callback)
177-
* @callback deleteDataByIdsCallback
209+
* Callback for QB.data.delete(className, requestedData, callback)
210+
* @callback deletedDataCallback
178211
* @param {object} error - The error object
179-
* @param {object} response - Empty body
212+
* @param {object|null} response
213+
* @param {array} response.deleted - Array of ids of deleted records. If you delete BY CRITERIA this property will be null.
214+
* @param {number} response.deletedCount - count of deleted records.
180215
*/
181-
this.service.ajax({url: Utils.getUrl(config.urls.data, className + '/' + id), type: 'DELETE', dataType: 'text'},
182-
function(err, result) {
183-
if (err) {
184-
callback(err, null);
185-
} else {
186-
callback (err, true);
216+
const typesData = {
217+
id: 1,
218+
ids: 2,
219+
criteria: 3
220+
};
221+
222+
let requestedTypeOf;
223+
224+
const responceNormalized = {
225+
deleted: [],
226+
deletedCount: 0
227+
};
228+
229+
const ajaxParams = {
230+
type: 'DELETE',
231+
dataType: 'text'
232+
};
233+
234+
/** Define what type of data passed by client */
235+
if(typeof requestedData === 'string') {
236+
requestedTypeOf = typesData.id;
237+
} else if(Utils.isArray(requestedData)) {
238+
requestedTypeOf = typesData.ids;
239+
} else if(Utils.isObject(requestedData)) {
240+
requestedTypeOf = typesData.criteria;
241+
}
242+
243+
if(requestedTypeOf === typesData.id) {
244+
ajaxParams.url = Utils.getUrl(config.urls.data, className + '/' + requestedData);
245+
} else if(requestedTypeOf === typesData.ids) {
246+
ajaxParams.url = Utils.getUrl(config.urls.data, className + '/' + requestedData.toString());
247+
} else if(requestedTypeOf === typesData.criteria) {
248+
ajaxParams.url = Utils.getUrl(config.urls.data, className + '/by_criteria');
249+
ajaxParams.data = requestedData;
250+
}
251+
252+
function handleDeleteCO(error, result) {
253+
if (error) {
254+
callback(error, null);
255+
} else {
256+
if(requestedTypeOf === typesData.id) {
257+
responceNormalized.deleted.push(requestedData);
258+
responceNormalized.deletedCount = responceNormalized.deleted.length;
259+
} else if(requestedTypeOf === typesData.ids) {
260+
const response = JSON.parse(result);
261+
responceNormalized.deleted = response.SuccessfullyDeleted.ids.slice(0);
262+
responceNormalized.deletedCount = responceNormalized.deleted.length;
263+
} else if(requestedTypeOf === typesData.criteria) {
264+
const response = JSON.parse(result);
265+
responceNormalized.deleted = null;
266+
responceNormalized.deletedCount = response.total_deleted;
187267
}
188-
});
268+
269+
callback (error, responceNormalized);
270+
}
271+
}
272+
273+
this.service.ajax(ajaxParams, handleDeleteCO);
189274
},
190275

191276
/**

0 commit comments

Comments
 (0)