Skip to content

Commit b56a425

Browse files
committed
Fleshed out the resource guide. #28
1 parent 8d16aa6 commit b56a425

File tree

3 files changed

+122
-28
lines changed

3 files changed

+122
-28
lines changed

Gruntfile.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ module.exports = function (grunt) {
207207
index: 1,
208208
overview: 2,
209209
basic: 3,
210-
advanced: 4
210+
advanced: 4,
211+
lifecycle: 5
211212
}
212213
},
213214
{

guide/overview/overview.doc

+12-12
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,13 @@ $scope.$watch(function () {
137137
}, function (lastModifiedTimestamp) {
138138
// When this callback is executed, it means that the data store thinks the item changed
139139

140-
// Retrieve the updated item from the server
140+
// Retrieve the updated item from the data store's cache
141141
$scope.document = DS.get('document', 45);
142142
});
143143
```
144144

145-
When the app starts up the calls to `lastModified()` and `get()` will both returned undefined, because the item isn't in
146-
the data store. If we insert `DS.find('document', 45);` right above the `$watch` function, the data store will make an
145+
When the app starts up, the calls to `lastModified()` and `get()` will both returned undefined, because the item isn't in
146+
the data store yet. If we insert the statement: `DS.find('document', 45);` right above the `$watch` function, the data store will make an
147147
AJAX request for that item. When the item returns from the server, the last modified timestamp for that item will change
148148
from `undefined` to something like `1388809123529`, causing the `get()` call inside the `$watch` callback function to be
149149
executed, retrieving the item from the data store and putting it on the `$scope`.
@@ -159,12 +159,12 @@ deleted. Example:
159159

160160
This document is in the data store for both users: `{ title: 'How to Cook', id: 45 }`
161161

162-
User #1
162+
User #1 (asynchronous)
163163
```js
164164
DS.destroy('document', 45).then(function (id) {...}); // sends DELETE request to the server
165165
```
166166

167-
User #2 receives notification from the server that document 45 was deleted
167+
User #2 receives notification from the server that document 45 was deleted and synchronously ejects it from the data store.
168168
```js
169169
DS.eject('document', 45); // synchronously eject document from the store
170170
```
@@ -180,7 +180,7 @@ See the [API](/documentation/api/api/index) for more information.
180180
@description
181181

182182
Angular-data ships with a number of asynchronous methods that facilitate communication between the data store and the
183-
persistence layer. These methods include the basic CRUD operations and wrappers for the `$http` service.
183+
persistence layer. These methods cover the basic CRUD operations.
184184

185185
The asynchronous methods return Promises produced by Angular's `$q` service.
186186

@@ -196,15 +196,17 @@ DS.find('document', 45).then(function (document) {
196196
DS.get('document', 45); // { title: 'How to Cook', id: 45 }
197197
});
198198

199-
DS.get('document', 45); // undefined
199+
DS.get('document', 45); // still undefined, because the find operation has not completed yet
200200
```
201201

202202
#### Another example
203203

204204
```js
205-
DS.get('document', 45); // { title: 'How to Cook', id: 45 }
205+
var document = DS.get('document', 45); // { title: 'How to Cook', id: 45 }
206206

207-
DS.update('document', 45, { title: 'How NOT to Cook' }).then(function (document) {
207+
document.title = 'How NOT to cook';
208+
209+
DS.save('document', 45).then(function (document) {
208210
document; // { title: 'How NOT to Cook', id: 45 }
209211

210212
// document 45 in the store has been updated
@@ -214,6 +216,4 @@ DS.update('document', 45, { title: 'How NOT to Cook' }).then(function (document)
214216
DS.get('document', 45); // { title: 'How to Cook', id: 45 }
215217
```
216218

217-
By using the data store's `update()` operation, the data store is able to update the last modified timestamp of the item
218-
so any code that's `$watch`ing the item can be notified of updates. If you directly modify attributes of items in the
219-
data store, the data store will not pick up on those updates.
219+
See the [API](/documentation/api/api/index) for more information.

guide/resource/resource.doc

+108-15
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,11 @@
55

66
# Resource Guide
77

8-
A _resource_ is the data and meta data associated with a particular RESTful endpoint.
9-
10-
You define _resources_ and register them with the data store. A _resource definition_ tells angular-data
11-
about a particular _resource_, like what its root endpoint is and which attribute refers to the primary key of the
12-
resource. A _resource definition_ can also specify validation functions to be executed before create and update
13-
operations.
14-
15-
See [defineResource(definition)](/documentation/api/api/DS.sync_methods:defineResource) for detailed API information.
8+
<page-list></page-list>
169

1710
@doc overview
1811
@id overview
19-
@name Resource Guide
12+
@name Overview
2013
@description
2114

2215
A _resource_ is the data and meta data associated with a particular RESTful endpoint.
@@ -42,9 +35,9 @@ DS.defineResource('document');
4235
With this definition the data store assumes the following:
4336

4437
- Resource will be referred to as `"document"`
45-
- The RESTful endpoint for this resource is `"/document"`
46-
- The `idAttribute` (attribute that specifies the primary key) is `"id"`
47-
- This resource does not use any validation
38+
- The RESTful endpoint for this resource is `DSProvider.defaults.baseUrl + "/document"`
39+
- The primary key is specified by the `"id"` property (or whatever is specified by `DSProvider.defaults.idAttribute`)
40+
- This resource has no custom lifecycle hooks (unless `DSProvider.defaults` has some lifecycle hooks defined)
4841

4942
@doc overview
5043
@id advanced
@@ -58,6 +51,7 @@ DS.defineResource({
5851
name: 'document',
5952
idAttribute: '_id',
6053
endpoint: 'documents',
54+
baseUrl: 'https://example.com/api',
6155
validate: function (attrs, cb) {
6256
if (!angular.isObject(attrs) {
6357
cb('Must be an object!');
@@ -71,6 +65,105 @@ DS.defineResource({
7165
With this definition the data store understands the following:
7266

7367
- Resource will be referred to as `"document"`
74-
- The RESTful endpoint for this resource is `"/documents"`
75-
- The `idAttribute` (attribute that specifies the primary key) is `"_id"`
76-
- Before create/save operations the provided `validate` function must pass
68+
- The RESTful endpoint for this resource is `"https://example.com/api/documents"`
69+
- The primary key is specified by the `"_id"` property
70+
- Before create/save operations, the provided `validate` function is executed (and any lifecycle hooks defined in `DSProvider.defaults`)
71+
72+
See [DS.defineResource](/documentation/api/api/DS.sync_methods:defineResource) for the full resource definition specification.
73+
74+
@doc overview
75+
@id lifecycle
76+
@name Model Lifecycle Hooks
77+
@description
78+
79+
The following asynchronous operations support a model lifecycle:
80+
81+
### DS.create()
82+
83+
- `beforeValidate` - Default: `noop`
84+
- `validate` - Default: `noop`
85+
- `afterValidate` - Default: `noop`
86+
- `beforeCreate` - Default: `noop`
87+
- `create` - Implementation provided by adapter
88+
- `afterCreate` - Default: `noop`
89+
90+
### DS.save()
91+
92+
- `beforeValidate` - Default: `noop`
93+
- `validate` - Default: `noop`
94+
- `afterValidate` - Default: `noop`
95+
- `beforeUpdate` - Default: `noop`
96+
- `save` - Implementation provided by adapter
97+
- `afterUpdate` - Default: `noop`
98+
99+
### DS.destroy()
100+
101+
- `beforeValidate` - Default: `noop`
102+
- `validate` - Default: `noop`
103+
- `afterValidate` - Default: `noop`
104+
- `beforeDestroy` - Default: `noop`
105+
- `destroy` - Implementation provided by adapter
106+
- `afterDestroy` - Default: `noop`
107+
108+
### Define lifecycle hooks
109+
All lifecycle hooks will be executed according to the following signature:
110+
```js
111+
exampleHook(resourceName, attrs, cb) {...}
112+
```
113+
114+
`resourceName` is the name of the resource that `attrs` belong to, which is a reference to the object on which `create`,
115+
`save` or `destroy` was originally called.
116+
117+
`cb` is the callback function to be executed when the lifecycle hook is done. `cb` follows the Node style of callbacks,
118+
where the first passed argument will be the error, if any, and the second is the result. In the case of these lifecycle
119+
functions, `attrs` _is_ the result. So, `attrs` is available for inspection and/or modification, and then should be passed
120+
to `cb`. For example:
121+
122+
```js
123+
validate(resourceName, attrs, cb) {
124+
console.log('hmm, looks good to me!');
125+
cb(null, attrs); // no error
126+
}
127+
```
128+
129+
```js
130+
validate(resourceName, attrs, cb) {
131+
console.log('something went wrong!');
132+
cb('some error'); // error!
133+
}
134+
```
135+
136+
The lifecycle will be aborted if `cb` receives an error or an error is thrown.
137+
138+
Finally, model lifecycle hooks can be defined at the global level or per-resource. For example:
139+
140+
```js
141+
angular.module('myApp', ['angular-data.DS'])
142+
.config(function (DSProvider) {
143+
144+
// Global definition
145+
DSProvider.defaults.beforeCreate = function (resourceName, attrs, cb) {
146+
console.log('Global beforeCreate');
147+
cb(null, attrs);
148+
};
149+
150+
})
151+
.run(function (DS) {
152+
153+
DS.defineResource({
154+
name: 'post',
155+
156+
// Local definition, overrides the global definition
157+
beforeCreate = function (resourceName, attrs, cb) {
158+
console.log('beforeCreate defined for ' + resourceName);
159+
cb(null, attrs);
160+
}
161+
});
162+
163+
// Will use the global definition
164+
DS.defineResource({
165+
name: 'comment'
166+
});
167+
168+
});
169+
```

0 commit comments

Comments
 (0)