Skip to content

Commit 62c926c

Browse files
committed
0.6.0
1 parent d69b0b3 commit 62c926c

File tree

7 files changed

+141
-65
lines changed

7 files changed

+141
-65
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
##### 0.6.0 - 17 January 2014
2+
3+
Added pluggable filters for the "where" clause of a query. Angular-data's "query language" will remain small and simple.
4+
Developers can provide their own more robust filters for more powerful queries.
5+
6+
###### Breaking API changes
7+
- #3 - Pluggable async adapters
8+
9+
###### Backwards API changes
10+
- #2 - angular-data query language
11+
- #4 - Query caching
12+
- #17 - Where predicates should be able to handle OR, not just AND
13+
114
##### 0.5.0 - 16 January 2014
215

316
###### Backwards API changes

dist/angular-data.js

+45-31
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,9 @@ function DSHttpAdapterProvider() {
10781078
},
10791079
deserialize: function (data) {
10801080
return data.data;
1081+
},
1082+
queryTransform: function (query) {
1083+
return query;
10811084
}
10821085
};
10831086

@@ -1292,6 +1295,9 @@ function DSHttpAdapterProvider() {
12921295
function findAll(resourceConfig, params, options) {
12931296
options = options || {};
12941297
options.params = options.params || {};
1298+
if (options.params.query) {
1299+
options.params.query = defaults.queryTransform(options.params.query);
1300+
}
12951301
DSUtils.deepMixIn(options, params);
12961302
return this.GET(
12971303
DSUtils.makePath(resourceConfig.baseUrl, resourceConfig.endpoint),
@@ -2227,7 +2233,8 @@ function save(resourceName, id, options) {
22272233
module.exports = save;
22282234

22292235
},{}],36:[function(require,module,exports){
2230-
var errorPrefix = 'DSProvider.registerAdapter(name, adapter): ';
2236+
var errorPrefix = 'DSProvider.registerAdapter(name, adapter): ',
2237+
utils = require('../utils')[0]();
22312238

22322239
function lifecycleNoop(resourceName, attrs, cb) {
22332240
cb(null, attrs);
@@ -2238,6 +2245,34 @@ function BaseConfig() {
22382245

22392246
BaseConfig.prototype.idAttribute = 'id';
22402247
BaseConfig.prototype.defaultAdapter = 'DSHttpAdapter';
2248+
BaseConfig.prototype.filter = function (resourceName, where, attrs) {
2249+
var keep = true;
2250+
utils.forOwn(where, function (clause, field) {
2251+
if (utils.isString(clause)) {
2252+
clause = {
2253+
'===': clause
2254+
};
2255+
}
2256+
if ('==' in clause) {
2257+
keep = keep && (attrs[field] == clause['==']);
2258+
} else if ('===' in clause) {
2259+
keep = keep && (attrs[field] === clause['===']);
2260+
} else if ('!=' in clause) {
2261+
keep = keep && (attrs[field] != clause['!=']);
2262+
} else if ('>' in clause) {
2263+
keep = keep && (attrs[field] > clause['>']);
2264+
} else if ('>=' in clause) {
2265+
keep = keep && (attrs[field] >= clause['>=']);
2266+
} else if ('<' in clause) {
2267+
keep = keep && (attrs[field] < clause['<']);
2268+
} else if ('<=' in clause) {
2269+
keep = keep && (attrs[field] <= clause['<=']);
2270+
} else if ('in' in clause) {
2271+
keep = keep && utils.contains(clause['in'], attrs[field]);
2272+
}
2273+
});
2274+
return keep;
2275+
};
22412276
BaseConfig.prototype.baseUrl = '';
22422277
BaseConfig.prototype.endpoint = '';
22432278
BaseConfig.prototype.beforeValidate = lifecycleNoop;
@@ -2314,7 +2349,7 @@ function DSProvider() {
23142349

23152350
module.exports = DSProvider;
23162351

2317-
},{"./async_methods":33,"./sync_methods":44}],37:[function(require,module,exports){
2352+
},{"../utils":"uE/lJt","./async_methods":33,"./sync_methods":44}],37:[function(require,module,exports){
23182353
var errorPrefix = 'DS.changes(resourceName, id): ';
23192354

23202355
/**
@@ -2673,7 +2708,8 @@ function filter(resourceName, params, options) {
26732708
}
26742709

26752710
try {
2676-
var resource = this.store[resourceName],
2711+
var definition = this.definitions[resourceName],
2712+
resource = this.store[resourceName],
26772713
_this = this;
26782714

26792715
// Protect against null
@@ -2691,38 +2727,16 @@ function filter(resourceName, params, options) {
26912727
}
26922728

26932729
// The query has been completed, so hit the cache with the query
2694-
var filtered = this.utils.filter(resource.collection, function (value) {
2695-
var keep = true;
2730+
var filtered = this.utils.filter(resource.collection, function (attrs) {
2731+
var keep = true,
2732+
where = params.query.where;
26962733

26972734
// Apply 'where' clauses
2698-
if (params.query.where) {
2699-
if (!_this.utils.isObject(params.query.where)) {
2735+
if (where) {
2736+
if (!_this.utils.isObject(where)) {
27002737
throw new _this.errors.IllegalArgumentError(errorPrefix + 'params.query.where: Must be an object!', { params: { query: { where: { actual: typeof params.query.where, expected: 'object' } } } });
27012738
}
2702-
_this.utils.forOwn(params.query.where, function (value2, key2) {
2703-
if (_this.utils.isString(value2)) {
2704-
value2 = {
2705-
'===': value2
2706-
};
2707-
}
2708-
if ('==' in value2) {
2709-
keep = keep && (value[key2] == value2['==']);
2710-
} else if ('===' in value2) {
2711-
keep = keep && (value[key2] === value2['===']);
2712-
} else if ('!=' in value2) {
2713-
keep = keep && (value[key2] != value2['!=']);
2714-
} else if ('>' in value2) {
2715-
keep = keep && (value[key2] > value2['>']);
2716-
} else if ('>=' in value2) {
2717-
keep = keep && (value[key2] >= value2['>=']);
2718-
} else if ('<' in value2) {
2719-
keep = keep && (value[key2] < value2['<']);
2720-
} else if ('<=' in value2) {
2721-
keep = keep && (value[key2] <= value2['<=']);
2722-
} else if ('in' in value2) {
2723-
keep = keep && _this.utils.contains(value2['in'], value[key2]);
2724-
}
2725-
});
2739+
keep = definition.filter(resourceName, where, attrs);
27262740
}
27272741
return keep;
27282742
});

dist/angular-data.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/adapters/http/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ function DSHttpAdapterProvider() {
88
},
99
deserialize: function (data) {
1010
return data.data;
11+
},
12+
queryTransform: function (query) {
13+
return query;
1114
}
1215
};
1316

@@ -222,6 +225,9 @@ function DSHttpAdapterProvider() {
222225
function findAll(resourceConfig, params, options) {
223226
options = options || {};
224227
options.params = options.params || {};
228+
if (options.params.query) {
229+
options.params.query = defaults.queryTransform(options.params.query);
230+
}
225231
DSUtils.deepMixIn(options, params);
226232
return this.GET(
227233
DSUtils.makePath(resourceConfig.baseUrl, resourceConfig.endpoint),

src/datastore/index.js

+30-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
var errorPrefix = 'DSProvider.registerAdapter(name, adapter): ';
1+
var errorPrefix = 'DSProvider.registerAdapter(name, adapter): ',
2+
utils = require('../utils')[0]();
23

34
function lifecycleNoop(resourceName, attrs, cb) {
45
cb(null, attrs);
@@ -9,6 +10,34 @@ function BaseConfig() {
910

1011
BaseConfig.prototype.idAttribute = 'id';
1112
BaseConfig.prototype.defaultAdapter = 'DSHttpAdapter';
13+
BaseConfig.prototype.filter = function (resourceName, where, attrs) {
14+
var keep = true;
15+
utils.forOwn(where, function (clause, field) {
16+
if (utils.isString(clause)) {
17+
clause = {
18+
'===': clause
19+
};
20+
}
21+
if ('==' in clause) {
22+
keep = keep && (attrs[field] == clause['==']);
23+
} else if ('===' in clause) {
24+
keep = keep && (attrs[field] === clause['===']);
25+
} else if ('!=' in clause) {
26+
keep = keep && (attrs[field] != clause['!=']);
27+
} else if ('>' in clause) {
28+
keep = keep && (attrs[field] > clause['>']);
29+
} else if ('>=' in clause) {
30+
keep = keep && (attrs[field] >= clause['>=']);
31+
} else if ('<' in clause) {
32+
keep = keep && (attrs[field] < clause['<']);
33+
} else if ('<=' in clause) {
34+
keep = keep && (attrs[field] <= clause['<=']);
35+
} else if ('in' in clause) {
36+
keep = keep && utils.contains(clause['in'], attrs[field]);
37+
}
38+
});
39+
return keep;
40+
};
1241
BaseConfig.prototype.baseUrl = '';
1342
BaseConfig.prototype.endpoint = '';
1443
BaseConfig.prototype.beforeValidate = lifecycleNoop;

src/datastore/sync_methods/filter/index.js

+8-29
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ function filter(resourceName, params, options) {
5353
}
5454

5555
try {
56-
var resource = this.store[resourceName],
56+
var definition = this.definitions[resourceName],
57+
resource = this.store[resourceName],
5758
_this = this;
5859

5960
// Protect against null
@@ -71,38 +72,16 @@ function filter(resourceName, params, options) {
7172
}
7273

7374
// The query has been completed, so hit the cache with the query
74-
var filtered = this.utils.filter(resource.collection, function (value) {
75-
var keep = true;
75+
var filtered = this.utils.filter(resource.collection, function (attrs) {
76+
var keep = true,
77+
where = params.query.where;
7678

7779
// Apply 'where' clauses
78-
if (params.query.where) {
79-
if (!_this.utils.isObject(params.query.where)) {
80+
if (where) {
81+
if (!_this.utils.isObject(where)) {
8082
throw new _this.errors.IllegalArgumentError(errorPrefix + 'params.query.where: Must be an object!', { params: { query: { where: { actual: typeof params.query.where, expected: 'object' } } } });
8183
}
82-
_this.utils.forOwn(params.query.where, function (value2, key2) {
83-
if (_this.utils.isString(value2)) {
84-
value2 = {
85-
'===': value2
86-
};
87-
}
88-
if ('==' in value2) {
89-
keep = keep && (value[key2] == value2['==']);
90-
} else if ('===' in value2) {
91-
keep = keep && (value[key2] === value2['===']);
92-
} else if ('!=' in value2) {
93-
keep = keep && (value[key2] != value2['!=']);
94-
} else if ('>' in value2) {
95-
keep = keep && (value[key2] > value2['>']);
96-
} else if ('>=' in value2) {
97-
keep = keep && (value[key2] >= value2['>=']);
98-
} else if ('<' in value2) {
99-
keep = keep && (value[key2] < value2['<']);
100-
} else if ('<=' in value2) {
101-
keep = keep && (value[key2] <= value2['<=']);
102-
} else if ('in' in value2) {
103-
keep = keep && _this.utils.contains(value2['in'], value[key2]);
104-
}
105-
});
84+
keep = definition.filter(resourceName, where, attrs);
10685
}
10786
return keep;
10887
});

test/integration/datastore/sync_methods/filter/index.test.js

+37-2
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,15 @@ describe('DS.filter(resourceName, params[, options])', function () {
211211

212212
assert.deepEqual(DS.filter('post', params), [p4, p1, p3, p2], 'should accept a single string and sort in ascending for strings');
213213

214-
params.query.orderBy = [['age', 'DESC']];
214+
params.query.orderBy = [
215+
['age', 'DESC']
216+
];
215217

216218
assert.deepEqual(DS.filter('post', params), [p4, p3, p2, p1], 'should accept an array of an array and sort in descending for numbers');
217219

218-
params.query.orderBy = [['author', 'DESC']];
220+
params.query.orderBy = [
221+
['author', 'DESC']
222+
];
219223

220224
assert.deepEqual(DS.filter('post', params), [p2, p3, p1, p4], 'should accept an array of an array and sort in descending for strings');
221225

@@ -310,6 +314,37 @@ describe('DS.filter(resourceName, params[, options])', function () {
310314
params.query.skip = 3;
311315
assert.deepEqual(DS.filter('post', params), [p4], 'should limit to 1 and skip 3');
312316

317+
done();
318+
});
319+
it('should allow custom "where" filter function', function (done) {
320+
DS.defineResource({
321+
name: 'comment',
322+
filter: function (resourceName, where, attrs) {
323+
return attrs.author === where.author.EQUALS || attrs.age % where.age.MOD === 1;
324+
}
325+
});
326+
assert.doesNotThrow(function () {
327+
DS.inject('comment', p1);
328+
DS.inject('comment', p2);
329+
DS.inject('comment', p3);
330+
DS.inject('comment', p4);
331+
}, Error, 'should not throw an error');
332+
333+
var params = {
334+
query: {
335+
where: {
336+
author: {
337+
'EQUALS': 'John'
338+
},
339+
age: {
340+
'MOD': 30
341+
}
342+
}
343+
}
344+
};
345+
346+
assert.deepEqual(DS.filter('comment', params), [p1, p2], 'should keep p1 and p2');
347+
313348
done();
314349
});
315350
});

0 commit comments

Comments
 (0)