Skip to content

HTTPS clone URL

Subversion checkout URL

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