Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 209 lines (152 sloc) 5.669 kb
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
1 # resourceful
2
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
3 A storage agnostic resource-oriented ODM for building prototypical models with validation and sanitization.
4
5 ## Example
6
7 ``` js
8 var resourceful = require('resourceful');
9
10 var Creature = resourceful.define('creature', function () {
11 //
12 // Specify a storage engine
13 //
14 this.use('couchdb');
15
16 //
17 // Specify some properties with validation
18 //
888cd2d @mmalecki [docs] Fix example in `README.md`
mmalecki authored
19 this.property('diet'); // Defaults to String
20 this.property('vertebrate', Boolean);
21 this.property('belly', Array);
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
22 });
23
24 //
25 // Now that the `Creature` prototype is defined
26 // we can add custom logic to be available on all instances
27 //
28 Creature.prototype.feed = function (food) {
29 this.belly.push(food);
30 };
31 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
32
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
33 ## Motivation
34 How often have you found yourself writing Model code in your application? Pretty often? Good! Unlike other "Object-Document Mappers" `resourceful` tries to only focus on two things:
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
35
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
36 1. A simple API for defining custom Model prototypes with validation. **No special sugar is required to instantiate prototypes defined by resourceful.**
37 2. Define an extensibility model for databases to provide CRUD functionality to Models along with custom query, filtering or updating specific to that specific implementation (Mongo, CouchDB, Redis, etc).
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
38
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
39 ## API Documentation
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
40
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
41 ### Defining resources
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
42
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
43 Here's the simplest of resources:
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
44
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
45 ``` js
46 var Creature = resourceful.define('creature');
47 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
48
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
49 The returned `Creature` object is a *resource constructor*, in other words, a *function*. Now let's add some properties to this constructor:
50
51 ``` js
52 Creature.property('diet'); // Defaults to String
53 Creature.property('vertebrate', Boolean);
54 Creature.property('belly', Array);
55 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
56
57 And add a method to the prototype:
58
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
59 ``` js
60 Creature.prototype.feed = function (food) {
61 this.belly.push(food);
62 };
63 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
64
65 Now lets instantiate a Creature, and feed it:
66
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
67 ``` js
68 var wolf = new(Creature)({
69 diet: 'carnivor',
70 vertebrate: true
71 });
72
73 wolf.feed('squirrel');
74 console.dir(wolf.belly);
75 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
76
77 You can also define resources this way:
78
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
79 ``` js
80 var Creature = resourceful.define('creature', function () {
81 this.property('diet');
82 this.property('vertebrate', Boolean);
83 this.property('belly', Array);
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
84
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
85 this.prototype.feed = function (food) {
86 this.belly.push(food);
87 };
88 });
89 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
90
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
91 ### Defining properties with Resource.property
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
92
93 Lets define a *legs* property, which is the number of legs the creature has:
94
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
95 ``` js
96 Creature.property('legs', Number);
97 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
98
99 Note that this form is equivalent:
100
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
101 ``` js
102 Creature.property('legs', 'number');
103 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
104
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
105 If we wanted to constrain the possible values the property could take, we could pass in an object as the last parameter:
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
106
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
107 ``` js
108 Creature.property('legs', Number, {
109 required: true,
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
110
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
111 minimum: 0,
112 maximum: 8,
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
113
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
114 assert: function (val) {
115 return val % 2 === 0;
116 }
117 });
118 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
119
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
120 Now resourceful won't let `Creature` instances be saved unless the *legs* property has a value between `0` and `8`, and is *even*,
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
121
122 This style is also valid for defining properties:
123
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
124 ``` js
125 Creature.property('legs', Number)
126 .required()
127 .minimum(0)
128 .maximum(8)
129 .assert(function (val) { return val % 2 === 0 });
130 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
131
132 If you want to access and modify an already defined property, you can do it this way:
133
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
134 ``` js
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
135 Creature.properties['legs'].maximum(6);
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
136 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
137
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
138 ### Saving and fetching resources
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
139
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
140 ``` js
141 Wolf.create({ name: 'Wolverine', age: 68 }, function (err, wolf) {
142 if (err) { throw new(Error)(err) }
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
143
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
144 console.log(wolf); // { _id: 42, resource: 'wolf', name: 'Wolverine', age: 68 }
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
145
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
146 wolf.age++;
147 wolf.save(function (err) {
148 if (!err) {
149 console.log('happy birthday ' + wolf.name + '!');
150 }
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
151 });
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
152 });
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
153
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
154 Wolf.get(42, function (err, wolf) {
155 if (err) { throw new(Error)(err) }
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
156
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
157 wolf.update({ fur: 'curly' }, function (e, wolf) {
158 console.log(wolf.fur); // "curly"
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
159 });
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
160 });
161 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
162
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
163 ### Resource constructor methods
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
164
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
165 These methods are available on all user-defined resource constructors, as well as on the default `resourceful.Resource` constructor. In other "classy" languages these can be thought of as Class methods.
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
166
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
167 * `Resource.get(id, [callback])`: Fetch a resource by *id*.
168 * `Resource.update(id, properties, [callback])`: Update a resource with properties.
169 * `Resource.destroy(id, [callback])`: Destroy a resource by *id*.
170 * `Resource.all([callback])`: Fetches all resources of this type.
171 * `Resource.save(inst, [callback])`: Saves the specified resource instance `inst` by overwriting all properties.
172 * `Resource.create(properties, [callback])`: Creates a new instance of the Resource with the specified `properties`
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
173
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
174 ### Resource prototype methods
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
175
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
176 These are the *prototype* methods, available on resource instances created with the `new` operator. In other "classy" languages these can be thought of as Instance methods
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
177
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
178 * `Resource.prototype.save([callback])`
179 * `Resource.prototype.update(properties, [callback])`
180 * `Resource.prototype.destroy([callback])`
181 * `Resource.prototype.reload([callback])`
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
182
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
183 ## Installation
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
184
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
185 ### Installing npm (node package manager)
186 ``` bash
187 $ curl http://npmjs.org/install.sh | sh
188 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
189
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
190 ### Installing resourceful
191 ``` bash
192 $ [sudo] npm install resourceful
b717b23 @indexzero [dist] Fix typo in README.md
indexzero authored
193 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
194
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
195 ## Tests
196 All tests are written with [vows][0] and should be run with [npm][1]:
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
197
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
198 ``` bash
199 $ npm test
200 ```
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
201
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
202 #### Author: [Alexis Sellier](http://cloudhead.io), [Charlie Robbins](http://nodejitsu.com)
203 #### Contributors: [Fedor Indutny](http://github.com/indutny), [Bradley Meck](http://github.com/bmeck)
204 #### License: Apache 2.0
08d810f @indexzero [doc] Added LICENSE and README.md
indexzero authored
205
d985319 @indexzero [doc] Update README.md and package.json
indexzero authored
206 [0]: http://vowsjs.org
888cd2d @mmalecki [docs] Fix example in `README.md`
mmalecki authored
207 [1]: http://npmjs.org
208
Something went wrong with that request. Please try again.