-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
299 lines (218 loc) · 9.92 KB
/
index.html
File metadata and controls
299 lines (218 loc) · 9.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>brainy.io</title>
<style type="text/css">
body {
background: #fefefe;
font-family: menlo;
}
h1, h2, h3, h4, h5, h6 {
font-family: monospace, prestige;
}
h2 {
margin-top: 100px;
}
h3 {
font-size: 20px;
margin-top: 50px;
}
h5 {
font-size: 16px;
margin: 35px 0 0 0;
}
a {
color: #5fba3d;
text-decoration: underline;
}
pre {
background: #efefef;
padding: 10px 15px;
overflow-x: auto;
}
#sidebar {
background: #fefefe;
position: fixed;
z-index: 10;
top: 0;
left: 0;
bottom: 0;
width: 200px;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
padding: 30px 0 30px 30px;
border-right: 1px solid #bbb;
box-shadow: 0 0 20px #ccc; -webkit-box-shadow: 0 0 20px #ccc; -moz-box-shadow: 0 0 20px #ccc;
}
#sidebar h4 {
margin-bottom: 5px;
margin-top: 20px;
}
#sidebar h4:first-child {
margin-top: 0;
}
#sidebar ul {
list-style: none;
padding: 0 0 0 10px;
margin: 0;
}
#content {
position: relative;
width: 550px;
margin: 30px 0 30px 260px;
}
</style>
</head>
<body>
<div id="sidebar">
<h4><a href="#">brainy (0.0.2)</a></h4>
<ul>
<li><a href="http://github.com/brainyio" rel="external" target="_blank">on GitHub</a></li>
</ul>
<h4><a href="#introduction">introduction</a></h4>
<h4><a href="#api">api</a></h4>
<ul>
<li><a href="#api-models">models</a></li>
<li><a href="#api-collections">collections</a></li>
</ul>
<h4><a href="#resources">resources</a></h4>
<ul>
<li><a href="#resources-idAttribute">idAttribute</a></li>
<li><a href="#resources-url">url</a></li>
<li><a href="#resources-urlRoot">urlRoot</a></li>
<li><a href="#resources-fetch">fetch</a></li>
<li><a href="#resources-validate">validate</a></li>
</ul>
</div>
<div id="content">
<h1>brainy.io</h1>
<p>brainy is a set of tools for sharing <a href="http://backbonejs.org">Backbone</a> code between the client and the server. brainy allows you to write a Backbone client application without regard for the server. it creates the server for you.</p>
<p>because it relies on REST and Backbone best practices, if you are familiar with both, you can create a brainy application.</p>
<h2 id="introduction">introduction</h2>
<p>when writing a front-end web application with Backbone, you are typically targeting some remote api. for rapid prototyping this poses two problems. first, you are rewriting models that likely have very similar definitions on the server. secondly, of course, it requires you have an api.</p>
<p>brainy solves these problems by analyzing your Backbone models and collections (<a href="#resources">resources</a>), and creating the <a href="#api">api</a> they require.</p>
<p>if you've not already, try <a href="https://github.com/brainyio/brainy-server/wiki/creating-a-brainy-application" target="_blank" st>creating a brainy application</a>.</p>
<h2 id="api">api</h2>
<p>when you start brainy it will create a RESTful API based on the (<a href="#resources">resources</a>) it's given. collections and models expose different endpoints and support different HTTP methods. the endpoint names reflect url and urlRoot properties of collections and models respectively.</p>
<p>because your resources are shared between the client and server, the resource methods you define (fetch, save, etc) are run in both contexts. this is useful for scenarios like <a href="#resources-validate">validation</a>. this can be acheived by overriding <em>save</em>, <em>destroy</em> etc. to return errors if some condition is not satisfied, which will be verified by the client and the server.</p>
<h3 id="api-models">models</h3>
<p>when given a model, brainy will create the following HTTP endpoints for creating, reading, updating, and deleting models. we will use the following model definition for endpoint examples.</p>
<pre>
var Post = Backbone.Model.extend({
idAttribute: '_id',
urlRoot: '/posts'
});</pre>
<h5>POST /:urlRoot</h5>
<p>creates and returns a new model, or 400 if the model is invalid. model attributes should be passed in through the request body.</p>
<pre>
$ curl -X POST -d 'text=foo&username=catshirt' /posts
{
"text": "foo",
"username": "catshirt",
"_id": "512a40f1163dcb4bce000001"
}</pre>
<h5>GET /:urlRoot/:id</h5>
<p>returns a single model, or 404 if not found. additional parameters passed through in the querystring are interpreted as a mongodb query. if a query is used, the model will only be returned if it matches that query.</p>
<pre>
$ curl -X GET /posts/512a40f1163dcb4bce000001
{
"text": "foo",
"username": "catshirt",
"_id": "512a40f1163dcb4bce000001"
}</pre>
<h5>PUT /:urlRoot/:id</h5>
<p>updates and returns the updated model, or 400 if the model is invalid. differs from PATCH in that PUT requires all attributes of the model to be sent. model attributes should be passed in through the request body.</p>
<pre>
$ curl -X PUT -d 'text=putted&username=catshirt' /posts/512a40f1163dcb4bce000001
{
"text": "putted",
"username": "catshirt",
"_id": "512a40f1163dcb4bce000001"
}</pre>
<h5>PATCH /:urlRoot/:id</h5>
<p>updates and returns the updated model, or 400 if the model is invalid. differs from PUT in that PATCH can accept a subset of attributes. model attributes should be passed in through the request body.</p>
<pre>
$ curl -X PUT -d 'text=patched' /posts/512a40f1163dcb4bce000001
{
"text": "patched",
"username": "catshirt",
"_id": "512a40f1163dcb4bce000001"
}</pre>
<h5>DELETE /:urlRoot/:id</h5>
<pre>
$ curl -X DELETE /posts/512a40f1163dcb4bce000001
OK</pre>
<p>deletes a model and returns 200, or 404 if the model is not found.</p>
<h3 id="api-collections">collections</h3>
<p>when given a collection, brainy will create an HTTP endpoint for reading and querying models as a collection. we will use the following collection definition for endpoint examples.</p>
<pre>
var Posts = Backbone.Collection.extend({
url: '/posts',
model: Post
});</pre>
<h5>GET /:url</h5>
<p>returns the entire collection of models, or [] if empty. additional parameters passed in the querystring are interpreted as a mongodb query. if a query is used, the collection will only return models that satisfy the query.</p>
<pre>
$ curl -X GET /posts
[{
"text": "foo",
"username": "catshirt",
"_id": "512a40f1163dcb4bce000001"
}]</pre>
<pre>
$ curl -X GET /posts?text[$regex]=boo
[]</pre>
<h2 id="resources">resources</h2>
<p>resources are simply any Backbone model or collection. because brainy doesn't modify Backbone api in any way, resources will behave as expected in the browser. brainy instead creates an additional context on the server in which your resources can operate.</p>
<h3 id="resources-idAttribute">idAttribute</h3>
<p>because brainy's primary data store is mongodb, you should assign <em>_id</em> to your model's idAttribute.</p>
<pre>
var Post = Backbone.Model.extend({
idAttribute: '_id'
});</pre>
<h3 id="resources-urlRoot">urlRoot</h3>
<p>similar to a collection's url, urlRoot is required for all models. urlRoot is used to infer a mongodb collection name and expose HTTP endpoints.</p>
<pre>
var Post = Backbone.Model.extend({
idAttribute: '_id',
urlRoot: '/posts'
});</pre>
<h3 id="resources-url">url</h3>
<p>per usual Backbone practice, collections all require a url property or function. brainy relies on this well for two purposes: inferring a mongodb collection name, and exposing HTTP endpoints.</p>
<pre>
var PostsCollection = Backbone.Collection.extend({
urlRoot: '/posts',
model: Post
});</pre>
<h3 id="resources-fetch">fetch</h3>
<p>resource fetch() functions behave as you'd expect them to in Backbone, but the nature of the HTTP api audments this function with an additional querying feature. by nature of jQuery's ajax method, the `data` value of `options` is serialized as a query string. the brainy api uses this query string to execute mongodb queries, meaning you can search collections through fetch:</p>
<pre>
var posts = new PostsCollection;
posts.fetch({
data: {
text: {
$regex: 'boo'
}
}
});</pre>
<h3 id="resources-validate">validate</h3>
<p>validate, like all resource functions, runs on both the client and the server. if a model invalidates on the client, the request is not sent. if the request is sent, validate is run again by the server. this means your api can validate requests sent from any client.</p>
<pre>
var Post = Backbone.Model.extend({
idAttribute: '_id',
urlRoot: '/posts',
validate: function(attrs) {
var err = undefined;
if (!attrs.text) {
err = 'text cannot be empty';
}
return err;
}
});</pre>
<p>in the example above, validate behaves as expected on the client, triggering the 'invalid' event on the model. validate on the server however, instead returns a 400 response code with the invalidation error in the response body.</p>
<p>Backbone only supports synchronous validation. this means asynchronous validation (querying other resources, etc) cannot be acheived through validate. a fair work around to this is to add your asynchronous checks to save or fetch, only calling the super function if your check passes.</p>
</div>
</body>
</html>