Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 658 lines (507 sloc) 24.75 kb
cd6c915 Simple prefetching works.
zef authored
1 persistence.js
2 ==============
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
3 `persistence.js` is a asynchronous Javascript object-relational
4 mapper library. It can be used both in the web browser and on
5 the server using [node.js](http://nodejs.org). It currently
6 supports 4 types of data stores:
7
8 * [HTML5 WebSQL database](http://dev.w3.org/html5/webdatabase/), a
9 somewhat controversial part of HTML5 that is supported in Webkit
10 browsers, specifically on mobile devices, including iPhone, Android
11 and Palm's WebOS.
12 * [Google Gears](http://gears.google.com), a browser plug-in that adds
13 a number of feature to the browser, including a in-browser database.
14 * [MySQL](http://www.mysql.com), using the
8e903cc @zefhemel Changed used mysql connector
zefhemel authored
15 [node-mysql](http://github.com/felixge/node-mysql), node.js module
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
16 on the server.
17 * In-memory, as a fallback. Keeps the database in memory and is cleaned
18 upon a page refresh (or server restart).
19
20 There is also an experimental support for [Qt 4.7 Declarative UI
21 framework
22 (QML)](http://doc.trolltech.org/4.7-snapshot/declarativeui.html) which
23 is an extension to JavaScript.
1b2c013 @zefhemel Documentation tweaks to accomodate for server environments.
zefhemel authored
24
25 For browser use, `persistence.js` has no dependencies on any other
26 frameworks, other than the Google Gears [initialization
27 script](http://code.google.com/apis/gears/gears_init.js), in case you
28 want to enable Gears support.
cd6c915 Simple prefetching works.
zef authored
29
3d5d3f0 @zefhemel Fixes to node blogging example, and description of plug-ins added to
zefhemel authored
30 Plug-ins
31 --------
32
33 There are a few `persistence.js` plug-ins available that add functionality:
34
35 * `persistence.search.js`, adds simple full-text search capabilities,
36 see `docs/search.md` for more information.
37 * `persistence.migrations.js`, supports data migrations (changes to
38 the database schema), see `docs/migrations.md` for more information.
39 * `persistence.sync.js`, supports database synchronization with a
40 remote server, see `docs/sync.md` for more information.
41
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
42 A Brief Intro to Async Programming
43 ----------------------------------
bf2edb5 More info on asynchronous programming
Zef Hemel authored
44
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
45 In browsers, Javascript and the web page's rendering engine share
46 a single thread. The result of this is that only one thing can happen
47 at a time. If a database query would be performed _synchronously_,
48 like in many other programming environments like Java and PHP the
49 browser would freeze from the moment the query was issued until the
50 results came back. Therefore, many APIs in Javascript are defined as
51 _asynchronous_ APIs, which mean that they do not block when an
52 "expensive" computation is performed, but instead provide the call
53 with a function that will be invoked once the result is known. In the
54 meantime, the browser can perform other duties.
bf2edb5 More info on asynchronous programming
Zef Hemel authored
55
56 For instance, a synchronous database call call would look as follows:
57
58 var results = db.query("SELECT * FROM Table");
59 for(...) { ... }
60
61 The execution of the first statement could take half a second, during
62 which the browser doesn't do anything else. By contrast, the
63 asynchronous version looks as follows:
64
65 db.query("SELECT * FROM Table", function(results) {
66 for(...) { ... }
67 });
68
69 Note that there will be a delay between the `db.query` call and the
70 result being available and that while the database is processing the
71 query, the execution of the Javascript continues. To make this clear,
72 consider the following program:
73
74 db.query("SELECT * FROM Table", function(results) {
75 console.log("hello");
76 });
77 console.log("world");
78
79 Although one could assume this would print "hello", followed by
80 "world", the result will likely be that "world" is printed before
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
81 "hello", because "hello" is only printed when the results from the
bf2edb5 More info on asynchronous programming
Zef Hemel authored
82 query are available. This is a tricky thing about asynchronous
83 programming that a Javascript developer will have to get used to.
84
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
85 Using persistence.js in the browser
86 ===================================
87
14f8aac Working on the readme
Zef Hemel authored
88 Browser support
89 ---------------
90
91 * Modern webkit browsers (Google Chrome and Safari)
92 * Firefox (through Google Gears)
792501e @zefhemel Working on selectJSON, refactoring some code.
zefhemel authored
93 * Android browser (tested on 1.6 and 2.x)
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
94 * iPhone browser (iPhone OS 3+)
06e6304 Added WebOS to supported platforms.
Zef Hemel authored
95 * Palm WebOS (tested on 1.4.0)
cd6c915 Simple prefetching works.
zef authored
96
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
97 (The following is being worked on:)
14f8aac Working on the readme
Zef Hemel authored
98 Internet Explorer is likely not supported (untested) because it
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
99 lacks `__defineGetter__` and `__defineSetter__` support, which
100 `persistence.js` uses heavily. This may change in IE 8.
14f8aac Working on the readme
Zef Hemel authored
101
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
102 Setting up
103 ----------
104
105 To use `persistence.js` you need to clone the git repository:
106
107 git clone git://github.com/zefhemel/persistencejs.git
108
559e75c @zefhemel Doc update
zefhemel authored
109 To use it you need to copy `lib/persistence.js` to your web directory,
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
110 as well as any data stores you want to use. Note that the `mysql` and
111 `websql` stores both depend on the `sql` store. A typical setup
559e75c @zefhemel Doc update
zefhemel authored
112 requires you to copy at least `lib/persistence.js`,
113 `lib/persistence.store.sql.js` and `lib/persistence.store.websql.js` to your
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
114 web directory. You can then load them as follows:
115
116 <script src="persistence.js" type="application/javascript"></script>
117 <script src="persistence.store.sql.js" type="application/javascript"></script>
118 <script src="persistence.store.websql.js" type="application/javascript"></script>
119
14f8aac Working on the readme
Zef Hemel authored
120
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
121 Setup your database
122 -------------------
cd6c915 Simple prefetching works.
zef authored
123
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
124 You need to explicitly configure the data store you want to use,
125 configuration of the data store is store-specific. The WebSQL store
126 (which includes Google Gears support) is configured as follows:
127
128 persistence.store.websql.config(persistence, 'yourdbname', 'A database description', 5 * 1024 * 1024);
129
130 The first argument is always supposed to be `persistence`. The second
131 in your database name (it will create it if it does not already exist,
132 the third is a description for you database, the last argument is the
133 maximum size of your database in bytes (5MB in this example).
134
135 If you're using the in-memory store, you can configure it as follows:
136
137 persistence.store.memory.config(persistence);
14f8aac Working on the readme
Zef Hemel authored
138
139 Schema definition
140 -----------------
141
142 A data model is declared using `persistence.define`. The following two
143 definitions define a `Task` and `Category` entity with a few simple
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
144 properties. The property types are based on [SQLite
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
145 types](http://www.sqlite.org/datatype3.html), specifically supported
146 types are (but any SQLite type is supported):
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
147
148 * `TEXT`: for textual data
149 * `INT`: for numeric values
150 * `BOOL`: for boolean values (`true` or `false`)
c65213f Added Fabio's Date type to documentation.
Zef Hemel authored
151 * `DATE`: for date/time value (with precision of 1 second)
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
152 * `JSON`: a special type that can be used to store arbitrary
153 [JSON](http://www.json.org) data. Note that this data can not be used
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
154 to filter or sort in any sensible way. If internal changes are made to a `JSON`
155 property, `persistence.js` may not register them. Therefore, a manual
156 call to `anObj.markDirty('jsonPropertyName')` is required before calling
157 `persistence.flush`.
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
158
159 Example use:
cd6c915 Simple prefetching works.
zef authored
160
73724ff Added .add and .remove methods to QueryCollections.
zef authored
161 var Task = persistence.define('Task', {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
162 name: "TEXT",
163 description: "TEXT",
164 done: "BOOL"
cd6c915 Simple prefetching works.
zef authored
165 });
166
73724ff Added .add and .remove methods to QueryCollections.
zef authored
167 var Category = persistence.define('Category', {
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
168 name: "TEXT",
169 metaData: "JSON"
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
170 });
171
172 var Tag = persistence.define('Task', {
173 name: "TEXT"
cd6c915 Simple prefetching works.
zef authored
174 });
175
14f8aac Working on the readme
Zef Hemel authored
176 The returned values are constructor functions and can be used to
177 create new instances of these entities later:
cd6c915 Simple prefetching works.
zef authored
178
179
14f8aac Working on the readme
Zef Hemel authored
180 Relationships between entities are defined using the constructor
181 function's `hasMany` call:
cd6c915 Simple prefetching works.
zef authored
182
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
183 // This defines a one-to-many relationship:
73724ff Added .add and .remove methods to QueryCollections.
zef authored
184 Category.hasMany('tasks', Task, 'category');
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
185 // These two definitions define a many-to-many relationship
186 Task.hasMany('tags', Tag, 'tasks');
187 Tag.hasMany('tasks', Task, 'tags');
cd6c915 Simple prefetching works.
zef authored
188
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
189 The first statement defines a `tasks` relationship on category objects
190 containing a `QueryCollection` (see the section on query collections
191 later) of `Task`s, it also defines an inverse relationship on `Task`
192 objects with the name `category`. The last two statements define a
193 many-to-many relationships between `Task` and `Tag`. `Task` gets a
194 `tags` property (a `QueryCollection`) containing all its tags and vice
195 versa, `Tag` gets a `tasks` property containing all of its tasks.
cd6c915 Simple prefetching works.
zef authored
196
14f8aac Working on the readme
Zef Hemel authored
197 The defined entity definitions are synchronized (activated) with the
198 database using a `persistence.schemaSync` call, which takes a callback
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
199 function (with a newly created transaction as an argument), that is called
14f8aac Working on the readme
Zef Hemel authored
200 when the schema synchronization has completed, the callback is
201 optional.
cd6c915 Simple prefetching works.
zef authored
202
203 persistence.schemaSync();
73724ff Added .add and .remove methods to QueryCollections.
zef authored
204 // or
14f8aac Working on the readme
Zef Hemel authored
205 persistence.schemaSync(function(tx) {
206 // tx is the transaction object of the transaction that was
207 // automatically started
208 });
cd6c915 Simple prefetching works.
zef authored
209
eae6f59 @fgrehm Finishing up documentation
fgrehm authored
210 There is also a migrations plugin you can check out, documentation can be found
58183c9 @fgrehm Fixing link to migrations documentation
fgrehm authored
211 in [persistence.migrations.docs.md](migrations/persistence.migrations.docs.md) file.
eae6f59 @fgrehm Finishing up documentation
fgrehm authored
212
71f97d7 first pass on mixins
Bruno Jouhier authored
213 Mix-ins
214 -------
215
216 You can also define mix-ins and apply them to entities of the model.
217
09d43e0 @zefhemel Documentation update
zefhemel authored
218 A mix-in definition is similar to an entity definition, except using
219 `defineMixin` rather than just `define`. For example:
71f97d7 first pass on mixins
Bruno Jouhier authored
220
09d43e0 @zefhemel Documentation update
zefhemel authored
221 var Annotatable = persistence.defineMixin('Annotatable', {
71f97d7 first pass on mixins
Bruno Jouhier authored
222 lastAnnotated: "DATE"
09d43e0 @zefhemel Documentation update
zefhemel authored
223 });
71f97d7 first pass on mixins
Bruno Jouhier authored
224
225 You can define relationships between mix-in and entities. For example:
226
227 // A normal entity
228 var Note = persistence.define('Note', {
229 text: "TEXT"
230 });
231
232 // relationship between a mix-in and a normal entity
233 Annotatable.hasMany('notes', Note, 'annotated');
234
235 Once you have defined a mix-in, you can apply it to any entity of your model,
236 with the `Entity.is(mixin)` method. For example:
237
b1ca96e fixed typo in readme
Bruno Jouhier authored
238 Project.is(Annotatable);
239 Task.is(Annotatable);
71f97d7 first pass on mixins
Bruno Jouhier authored
240
241 Now, your `Project` and `Task` entities have an additional `lastAnnotated` property.
242 They also have a one to many relationship called `notes` to the `Note` entity.
243 And you can also traverse the reverse relationship from a `Note` to its `annotated` object
244
245 Note that `annotated` is a polymorphic relationship as it may yield either a `Project`
246 or a `Task` (or any other entity which is `Annotatable').
247
248 Notes: this feature is very experimental at this stage. It needs more testing.
8db0de9 @zefhemel Doc typo fix
zefhemel authored
249 Support for "is a" relationships (classical inheritance) is also in the works.
71f97d7 first pass on mixins
Bruno Jouhier authored
250
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
251 Creating and manipulating objects
252 ---------------------------------
253
254 New objects can be instantiated with the constructor functions.
255 Optionally, an object with initial property values can be passed as
256 well, or the properties may be set later:
257
258 var task = new Task();
259 var category = new Category({name: "My category"});
1e94adf Some more JSON property examples + minified version.
Zef Hemel authored
260 category.metaData = {rating: 5};
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
261 var tag = new Tag();
262 tag.name = "work";
263
264 Many-to-one relationships are accessed using their specified name, e.g.:
265 task.category = category;
266
267 One-to-many and many-to-many relationships are access and manipulated
268 through the `QueryCollection` API that will be discussed later:
269
270 task.tags.add(tag);
271 tasks.tags.remove(tag)l
272 tasks.tags.list(tx, function(allTags) { console.log(allTags); });
273
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
274 Persisting/removing objects
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
275 ---------------------------
cd6c915 Simple prefetching works.
zef authored
276
14f8aac Working on the readme
Zef Hemel authored
277 Similar to [hibernate](http://www.hibernate.org), `persistence.js`
278 uses a tracking mechanism to determine which objects' changes have to
279 be persisted to the datase. All objects retrieved from the database
280 are automatically tracked for changes. New entities can be tracked to
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
281 be persisted using the `persistence.add` function:
cd6c915 Simple prefetching works.
zef authored
282
c37c40d Formatted readme slightly
Zef Hemel authored
283 var c = new Category({name: "Main category"});
284 persistence.add(c);
285 for ( var i = 0; i < 5; i++) {
286 var t = new Task();
287 t.name = 'Task ' + i;
288 t.done = i % 2 == 0;
289 t.category = c;
290 persistence.add(t);
291 }
cd6c915 Simple prefetching works.
zef authored
292
4941cd3 Added support for object removal (via `persistence.remove`).
Zef Hemel authored
293 Objects can also be removed from the database:
294
295 persistence.remove(c);
296
14f8aac Working on the readme
Zef Hemel authored
297 All changes made to tracked objects can be flushed to the database by
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
298 using `persistence.flush`, which takes a transaction object and
299 callback function as arguments. A new transaction can be started using
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
300 `persistence.transaction`:
cd6c915 Simple prefetching works.
zef authored
301
302 persistence.transaction(function(tx) {
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
303 persistence.flush(tx, function() {
304 alert('Done flushing!');
305 });
306 });
14f8aac Working on the readme
Zef Hemel authored
307
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
308 For convenience, it is also possible to not specify a transaction or
309 callback, in that case a new transaction will be started
310 automatically. For instance:
14f8aac Working on the readme
Zef Hemel authored
311
312 persistence.flush();
313 // or, with callback
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
314 persistence.flush(function() {
14f8aac Working on the readme
Zef Hemel authored
315 alert('Done flushing');
316 });
317
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
318 Note that when no callback is defined, the flushing still happens
319 asynchronously.
14f8aac Working on the readme
Zef Hemel authored
320
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
321 __Important__: Changes and new objects will not be persisted until you
322 explicitly call `persistence.flush()`. The exception to this rule is
e38fbe0 Got rid of redundancy in readme.
Zef Hemel authored
323 using the `list(...)` method on a database `QueryCollection`, which also
324 flushes first, although this behavior may change in the future.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
325
d61084e persistence.sync.js now keeps track of changes to all entities in
Zef Hemel authored
326 Dumping and restoring data
792501e @zefhemel Working on selectJSON, refactoring some code.
zefhemel authored
327 --------------------------
328
329 The library supports two kinds of dumping and restoring data.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
330
331 `persistence.dump` can be used to create an object containing a full
332 dump of a database. Naturally, it is adviced to only do this with
333 smaller databases. Example:
334
335 persistence.dump(tx, [Task, Category], function(dump) {
336 console.log(dump);
337 });
338
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
339 The `tx` is left out, a new transaction will be started for the
340 operation. If the second argument is left out, `dump` defaults
341 to dumping _all_ defined entities.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
342
343 The dump format is:
344
345 {"entity-name": [list of instances],
346 ...}
347
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
348 `persistence.load` is used to restore the dump produced by
349 `persistence.dump`. Usage:
350
351 persistence.load(tx, dumpObj, function() {
352 alert('Dump restored!');
353 });
354
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
355 The `tx` argument can be left out to automatically start a new
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
356 transaction. Note that `persistence.load` does not empty the database
357 first, it simply attempts to add all objects to the database. If
358 objects with, e.g. the same ID already exist, this will fail.
ef3606a A simple database dump function. Restore will come soon.
Zef Hemel authored
359
d61084e persistence.sync.js now keeps track of changes to all entities in
Zef Hemel authored
360 Similarly, `persistence.loadFromJson` and `persistence.dumpToJson`
361 respectively load and dump all the database's data as JSON strings.
362
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
363 Entity constructor functions
364 ----------------------------
365
366 The constructor function returned by a `persistence.define` call
367 cannot only be used to instantiate new objects, it also has some
368 useful methods of its own:
369
370 * `EntityName.all([session])` returns a query collection containing
371 all
372 persisted instances of that object. The `session` argument is
373 optional and only required when `persistence.js` is used in
374 multi-session mode.
375 * `EntityName.load([session], [tx], id, callback)` loads an particular
376 object from the database by id or returns `null` if it has not been
377 found.
378 * `EntityName.findBy([session], [tx], property, value, callback)` searches
379 for a particular object based on a property value (this is assumed to
380 be unique), the callback function is called with the found object or
381 `null` if it has not been found.
382
383 And of course the methods to define relationships to other entities:
384
385 * `EntityName.hasMany(property, Entity, inverseProperty)` defines a
386 1:N or N:M relationship (depending on the inverse property)
387 * `EntityName.hasOne(property, Entity)` defines a 1:1 or N:1
388 relationship
389
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
390
391 Entity objects
392 --------------
393
394 Entity instances also have a few predefined properties and methods you
395 should be aware of:
396
397 * `obj.id`, contains the identifier of your entity, this is a
398 automatically generated (approximation of a) UUID. You should
399 never write to this property.
400 * `obj.fetch(prop, callback)`, if an object has a `hasOne`
401 relationship to another which has not yet been fetched from the
402 database (e.g. when `prefetch` wasn't used), you can fetch in manually
403 using `fetch`. When the property object is retrieved the callback function
404 is invoked with the result, the result is also cached in the entity
405 object itself.
406 * `obj.selectJSON([tx], propertySpec, callback)`, sometime you need to extract
4c18f83 @zefhemel Another README fix...
zefhemel authored
407 a subset of data from an entity. You for instance need to post a
408 JSON representation of your entity, but do not want to include all
409 properties. `selectJSON` allows you to do that. The `propertySpec`
410 arguments expects an array with property names. Some examples:
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
411 * `['id', 'name']`, will return an object with the id and name property of this entity
412 * `['*']`, will return an object with all the properties of this entity, not recursive
413 * `['project.name']`, will return an object with a project property which has a name
11dedaf @zefhemel README fixes
zefhemel authored
414 property containing the project name (hasOne relationship)
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
415 * `['project.[id, name]']`, will return an object with a project property which has an
11dedaf @zefhemel README fixes
zefhemel authored
416 id and name property containing the project name (hasOne relationship)
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
417 * `['tags.name']`, will return an object with an array `tags` property containing
11dedaf @zefhemel README fixes
zefhemel authored
418 objects each with a single property: name
d714e0d @zefhemel Added `selectJSON` method to entity objects, see README.md for
zefhemel authored
419
420
14f8aac Working on the readme
Zef Hemel authored
421 Query collections
422 -----------------
423
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
424 A core concept of `persistence.js` is the `QueryCollection`. A
14f8aac Working on the readme
Zef Hemel authored
425 `QueryCollection` represents a (sometimes) virtual collection that can
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
426 be filtered, ordered or paginated. `QueryCollection`s are somewhate
427 inspired by [Google AppEngine's Query
428 class](http://code.google.com/appengine/docs/python/datastore/queryclass.html).
14f8aac Working on the readme
Zef Hemel authored
429 A `QueryCollection` has the following methods:
430
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
431 * `filter(property, operator, value)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
432 Returns a new `QueryCollection` that adds a filter, filtering a
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
433 certain property based on an operator and value. Supported operators
80824fe @zefhemel Introduced bug fixes, and new 'not in' operator.
zefhemel authored
434 are '=', '!=', '<', '<=', '>', '>=', 'in' and 'not in'. Example:
435 `.filter('done', '=', true)`
3843c74 @zefhemel Added or filters, usage (example in test/test.persistence.js):
zefhemel authored
436 * `or(filter)`
437 Returns a new `QueryCollection` that contains items either matching
438 the filters specified before calling `or`, or the filter represented
439 in the argument. The `filter` argument is of a `Filter` type, there
440 are three types of filters:
441 - `persistence.PropertyFilter`, which filters on properties (internally called when `filter(...)` is used.
442 Example: `new persistence.PropertyFilter('done', '=', true)`
443 - `persistence.AndFilter`, which is passed two filter objects as arguments, both of which should be true.
444 Example: `new persistence.AndFilter(new persistence.PropertyFilter('done', '=', true), new persistence.PropertyFilter('archived', '=', true))`
445 - `persistence.OrFilter`, which is passed two filter objects as arguments, one of which should be true.
446 Example: `new persistence.OrFilter(new persistence.PropertyFilter('done', '=', true), new persistence.PropertyFilter('archived', '=', true))`
447 * `and(filter)`
448 same as `or(filter)` except that both conditions should hold for items to be in the collection.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
449 * `order(property, ascending)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
450 Returns a new `QueryCollection` that will order its results by the
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
451 property specified in either an ascending (ascending === true) or
452 descending (ascending === false) order.
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
453 * `limit(n)`
454 Returns a new `QueryCollection` that limits the size of the result
455 set to `n` items. Useful for pagination.
456 * `skip(n)`
457 Returns a new `QueryCollection` that skips the first `n` results.
458 Useful for pagination.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
459 * `prefetch(rel)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
460 Returns a new `QueryCollection` that prefetches entities linked
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
461 through relationship `rel`, note that this only works for one-to-one
462 and many-to-one relationships.
a9fa189 @zefhemel Added `count` call to query collections. Fixed a little bug in
zefhemel authored
463 * `add(obj)`
464 Adds object `obj` to the collection.
465 * `remove(obj)`
466 Removes object `obj` from the collection.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
467 * `list([tx], callback)`
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
468 Asynchronously fetches the results matching the formulated query.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
469 Once retrieved, the callback function is invoked with an array of
470 entity objects as argument.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
471 * `each([tx], eachCallback)`
9520607 Basic implementation of LocalQueryCollection, only supports filtering
Zef Hemel authored
472 Asynchronously fetches the results matching the formulated query.
473 Once retrieved, the `eachCallback` function is invoked on each
474 element of the result objects.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
475 * `forEach([tx], eachCallback)`
476 Alias for `each`
477 * `one([tx], callback)`
a2c07b5 @zefhemel Added `destroyAll` method to DbQueryCollections to remove all the items
zefhemel authored
478 Asynchronously fetches the first element of the collection, or `null` if none.
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
479 * `destroyAll([tx], callback)`
a2c07b5 @zefhemel Added `destroyAll` method to DbQueryCollections to remove all the items
zefhemel authored
480 Asynchronously removes all the items in the collection. __Important__: this does
481 not only remove the items from the collection, but removes the items themselves!
e2d2c10 @zefhemel IMPORTANT: Minor breaking changes!
zefhemel authored
482 * `count([tx], callback)`
a9fa189 @zefhemel Added `count` call to query collections. Fixed a little bug in
zefhemel authored
483 Asynchronously counts the number of items in the collection. The arguments passed
484 to the `callback` function is the number of items.
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
485
486 Query collections are returned by:
487
488 * `EntityName.all()`, e.g. `Task.all()`
489 * one-to-many and many-to-many relationships, e.g. `task.tags`
490
491 Example:
cd6c915 Simple prefetching works.
zef authored
492
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
493 var allTasks = Task.all().filter("done", '=', true).prefetch("category").order("name", false).limit(10);
cd6c915 Simple prefetching works.
zef authored
494
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
495 allTasks.list(null, function (results) {
496 results.forEach(function (r) {
497 console.log(r.name)
498 window.task = r;
cd6c915 Simple prefetching works.
zef authored
499 });
500 });
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
501
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
502 Using persistence.js on the server
503 ==================================
504
dd1c7c4 @zefhemel Set-up library to be used a node library installable via npm. In fact,
zefhemel authored
505 Installing `persistence.js` on node is easy using [npm](http://npmjs.org):
506
507 npm install persistencejs
508
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
509 Sadly the node.js server environment requires slight changes to
510 `persistence.js` to make it work with multiple database connections:
511
512 * A `Session` object needs to be passed as an extra argument to
513 certain method calls, typically as a first argument.
514 * Methods previously called on the `persistence` object itself are now
515 called on the `Session` object.
516
517 An example `node.js` application is included in `test/node-blog.js`.
518
519 Setup
520 -----
521 You need to `require` two modules, the `persistence.js` library itself
dd1c7c4 @zefhemel Set-up library to be used a node library installable via npm. In fact,
zefhemel authored
522 and the MySQL backend module.
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
523
dd1c7c4 @zefhemel Set-up library to be used a node library installable via npm. In fact,
zefhemel authored
524 var persistence = require('persistencejs/persistence').persistence;
525 var persistenceStore = require('persistencejs/persistence.store.mysql');
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
526
527 Then, you configure the database settings to use:
528
8d922e1 @zefhemel Added port argument to documentation as well
zefhemel authored
529 persistenceStore.config(persistence, 'localhost', 3306, 'dbname', 'username', 'password');
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
530
531 Subsequently, for every connection you handle (assuming you're
532 building a sever), you call the `persistenceStore.getSession()`
533 method:
534
535 var session = persistenceBackend.getSession();
536
537 This session is what you pass around, typically together with a
538 transaction object. Note that currently you can only have one
539 transaction open per session and transactions cannot be nested.
540
541 session.transaction(function(tx) {
542 ...
543 });
544
96f2a57 documented commit/rollback feature
Bruno Jouhier authored
545 Commit and Rollback
546 -------------------
547
548 `persistence.js` works in autocommit mode by default.
549
550 You can override this behavior and enable explicit commit and rollback
551 by passing true as first argument to `persistence.transaction`.
552 You can then use the following two methods to control the transaction:
553
554 * `transaction.commit(session, callback)` commits the changes.
555 * `transaction.rollback(session, callback)` rollbacks the changes.
556
557 Typical code will look like:
558
559 session.transaction(true, function(tx) {
560 // create/update/delete objects
561 modifyThings(session, tx, function(err, result) {
562 if (err) {
563 // something went wrong
564 tx.rollback(session, function() {
565 console.log('changes have been rolled back: ' + ex.message);
566 });
567 }
568 else {
569 // success
570 tx.commit(session, function() {
571 console.log('changes have been committed: ' result);
572 });
573 });
574 });
575
576 Explicit commit and rollback is only supported on MySQL (server side)
577 for now.
578
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
579 Defining your data model
580 ------------------------
581
582 Defining your data model is done in exactly the same way as regular `persistence.js`:
583
584 var Task = persistence.define('Task', {
585 name: "TEXT",
586 description: "TEXT",
587 done: "BOOL"
588 });
589
590 A `schemaSync` is typically performed as follows:
591
592 session.schemaSync(tx, function() {
593 ...
594 });
595
596 Creating and manipulating objects
597 ---------------------------------
598
599 Creating and manipulating objects is done much the same way as with
600 regular `persistence.js`, except that in the entity's constructor you
601 need to reference the `Session` again:
602
603 var t = new Task(session);
604 ...
605 session.add(t);
606
607 session.flush(tx, function() {
608 ...
609 });
610
611 Query collections
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
612 -----------------
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
613
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
614 Query collections work the same way as in regular `persistence.js`
615 with the exception of the `Entity.all()` method that now also requires
616 a `Session` to be passed to it:
617
618 Task.all(session).filter('done', '=', true).list(tx, function(tasks) {
619 ...
620 });
621
622 Closing the session
623 -------------------
624
625 After usage, you need to close your session:
626
627 session.close();
628
629 Bugs and Contributions
630 ======================
631
127d79b Rewrote parts of readme. Added documentation for supported property
Zef Hemel authored
632 If you find a bug, please [report it](http://yellowgrass.org/project/persistence.js).
c65213f Added Fabio's Date type to documentation.
Zef Hemel authored
633 or fork the project, fix the problem and send me a pull request. For
b07a858 Moved issues to the issue tracker.
Zef Hemel authored
634 a list of planned features and open issues, have a look at the [issue
b5cd840 Changed location of issue tracker.
Zef Hemel authored
635 tracker](http://yellowgrass.org/project/persistence.js).
033f67a Added .limit(n) and .skip(n) support.
Zef Hemel authored
636
0302c86 Added link to Google Group
Zef Hemel authored
637 For support and discussion, please join the [persistence.js Google
638 Group](http://groups.google.com/group/persistencejs).
639
0e32d43 @zefhemel Added AUTHORS file
zefhemel authored
640 Thanks goes to the people listed in `AUTHORS` for their contributions.
c65213f Added Fabio's Date type to documentation.
Zef Hemel authored
641
cda1de2 @zefhemel Added link to the persistence.js GWT wrapper.
zefhemel authored
642 If you use [GWT](http://code.google.com/webtoolkit/) (the Google Web
643 Toolkit), be sure to have a look at [Dennis Z. Jiang's GWT persistence.js
644 wrapper](http://github.com/dennisjzh/gwt-persistence).
645
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
646 License
4537c59 @zefhemel Rewrite and fixes to the README
zefhemel authored
647 =======
90ea29b Extended README + license. Preparing for initial release.
Zef Hemel authored
648
649 This work is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
cb16171 Added flattr link
Zef Hemel authored
650
651 Support this work
3d5d3f0 @zefhemel Fixes to node blogging example, and description of plug-ins added to
zefhemel authored
652 -----------------
cb16171 Added flattr link
Zef Hemel authored
653
654 You can support this project by flattering it:
655
656 <a href="http://flattr.com/thing/2510/persistence-js" target="_blank">
657 <img src="http://api.flattr.com/button/button-static-50x60.png" title="Flattr this" border="0" /></a>
Something went wrong with that request. Please try again.