Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 54c83257119abab7351f34100496771386058b5a 0 parents
@dgeb dgeb authored
Showing with 378 additions and 0 deletions.
  1. +20 −0 LICENSE
  2. +134 −0 README.md
  3. +224 −0 src/ember-rest.js
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright 2012 Cerebris Corporation
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
134 README.md
@@ -0,0 +1,134 @@
+# Ember-REST
+
+A *very* simple library for RESTful resources in Ember.js.
+
+## Requirements
+
+Ember.js and jQuery.js
+
+## Usage
+
+### Ember.Resource
+
+Create models that extend Ember.Resource. For example:
+
+```
+App.Contact = Ember.Resource.extend({
+ url: '/contacts',
+ name: 'contact',
+ properties: ['first_name', 'last_name'],
+
+ validate: function() {
+ if (this.get('first_name') === undefined || this.get('first_name') === '' ||
+ this.get('last_name') === undefined || this.get('last_name') === '') {
+ return 'Contacts require a first and a last name.';
+ }
+ },
+
+ fullName: Ember.computed(function() {
+ return this.get('first_name') + ' ' + this.get('last_name');
+ }).property('first_name', 'last_name')
+});
+```
+
+Define the following properties for your models:
+
+ * `name` -- the name used to contain the serialized data in this object's JSON representation
+ * `properties` -- an array of property names to be returned in this object's JSON representation
+ * `url` -- (optional) the base url of the resource (e.g. '/contacts/active'); will default to the `url` for `type`
+
+You may wish to override / define the following methods:
+
+ * `serialize()` - generate this resource's JSON representation
+ * `serializeProperty(prop)` - generate an individual property's JSON representation
+ * `deserialize(json)`
+ * `deserializeProperty(prop, value)`
+ * `validate()` - parse values and return an error string or object if appropriate
+
+The following CRUD methods are available on resources:
+
+ * `save()` - create a new resource or update an existing one
+ * `destroy()` - delete an existing resource
+
+Here's an example of creating a new resource with `save()`:
+
+```
+ submitForm: function() {
+ var self = this;
+ var contact = this.get("contact");
+
+ contact.save()
+ .fail( function(e) {
+ App.displayError(e);
+ })
+ .done(function() {
+ App.contactsController.pushObject(contact);
+ self.get("parentView").hideNew();
+ });
+ }
+```
+
+Here's an almost identical example of updating an existing resource with `save()`:
+
+```
+ submitForm: function() {
+ var self = this;
+ var contact = this.get("contact");
+
+ contact.save()
+ .fail( function(e) {
+ App.displayError(e);
+ })
+ .done( function() {
+ var parentView = self.get("parentView");
+ parentView.get("contact").duplicateProperties(contact);
+ parentView.hideEdit();
+ });
+ }
+```
+
+And an example of deleting an existing resource with `destroy()`:
+
+```
+ destroyRecord: function() {
+ var contact = this.get("contact");
+
+ contact.destroy()
+ .done(function() {
+ App.contactsController.removeObject(contact);
+ });
+ }
+```
+
+### Ember.ResourceController
+
+Extend Ember.ResourceController to create controllers of resources. For example:
+
+```
+App.contactsController = Ember.ResourceController.create({
+ type: App.Contact
+});
+```
+
+Define the following properties for your controller:
+
+ * `type` -- an Ember.Resource class; the class must have a 'data' property that returns a JSON representation of the object
+ * `url` -- (optional) the base url of the resource (e.g. '/contacts/active'); will default to the `url` for `type`
+
+The following methods are available:
+
+ * `load(json)` -- create and load a single `Ember.Resource` from JSON
+ * `loadAll(json)` -- create and load `Ember.Resource` objects from a JSON array
+ * `findAll()` -- replace `contents` with an ajax call to `url`
+
+## Tests
+
+Coming soon...
+
+## Sample app
+
+https://github.com/dgeb/ember_rest_example
+
+## License
+
+Copyright 2012 Cerebris Corporation. MIT License (see LICENSE for details).
224 src/ember-rest.js
@@ -0,0 +1,224 @@
+/**
+ Ember-REST.js
+
+ A simple library for RESTful resources in Ember.js
+
+ Copyright (c) 2012 Cerebris Corporation
+
+ Licensed under the MIT license:
+ http://www.opensource.org/licenses/mit-license.php
+*/
+
+/**
+ A model class for RESTful resources
+
+ Extend this class and define the following properties:
+
+ * `name` -- the name used to contain the serialized data in this object's JSON
+ representation
+ * `properties` -- an array of property names to be returned in this object's
+ JSON representation
+ * `url` -- (optional) the base url of the resource (e.g. '/contacts/active');
+ will default to the `url` for `type`
+
+ You may also wish to override / define the following methods:
+
+ * `serialize()`
+ * `serializeProperty(prop)`
+ * `deserialize(json)`
+ * `deserializeProperty(prop, value)`
+ * `validate()`
+*/
+Ember.Resource = Ember.Object.extend({
+ name: Ember.required(),
+ properties: Ember.required(),
+ url: Ember.required(),
+
+ /**
+ Duplicate every property from another resource
+ */
+ duplicateProperties: function(source) {
+ var prop;
+ for(var i = 0; i < this.properties.length; i++) {
+ prop = this.properties[i];
+ this.set(prop, source.get(prop));
+ }
+ },
+
+ /**
+ Generate this resource's JSON representation
+
+ Override this or `serializeProperty` to provide custom serialization
+ */
+ serialize: function() {
+ var ret = {},
+ prop;
+
+ ret[this.name] = {};
+ for(var i = 0; i < this.properties.length; i++) {
+ prop = this.properties[i];
+ ret[this.name][prop] = this.serializeProperty(prop);
+ }
+ return ret;
+ },
+
+ /**
+ Generate an individual property's JSON representation
+
+ Override to provide custom serialization
+ */
+ serializeProperty: function(prop) {
+ return this.get(prop);
+ },
+
+ /**
+ Set this resource's properties from JSON
+
+ Override this or `deserializeProperty` to provide custom deserialization
+ */
+ deserialize: function(json) {
+ Ember.beginPropertyChanges(this);
+ for(var prop in json) {
+ if (json.hasOwnProperty(prop)) this.deserializeProperty(prop, json[prop]);
+ }
+ Ember.endPropertyChanges(this);
+ return this;
+ },
+
+ /**
+ Set an individual property from its value in JSON
+
+ Override to provide custom serialization
+ */
+ deserializeProperty: function(prop, value) {
+ this.set(prop, value);
+ },
+
+ /**
+ Create (if new) or update (if existing) record via ajax
+
+ Will call validate() if defined for this record
+
+ If successful, updates this record's id and other properties
+ by calling `deserialize()` with the data returned.
+ */
+ save: function() {
+ var self = this,
+ isNew = (this.get('id') === undefined);
+
+ if (this.validate !== undefined) {
+ var error = this.validate();
+ if (error) {
+ return {
+ fail: function(f) { f(error); return this; },
+ done: function() { return this; },
+ always: function(f) { f(); return this; }
+ };
+ }
+ }
+
+ return jQuery.ajax({
+ url: this._url(),
+ data: this.serialize(),
+ dataType: 'json',
+ type: (isNew ? 'POST' : 'PUT'),
+ success: function(json) {
+ // Update properties
+ if (json)
+ self.deserialize(json);
+ }
+ });
+ },
+
+ /**
+ Delete resource via ajax
+ */
+ destroy: function() {
+ var self = this;
+
+ return jQuery.ajax({
+ url: this._url(),
+ dataType: 'json',
+ type: 'DELETE'
+ });
+ },
+
+ /**
+ @private
+
+ The URL for this resource, based on `url` and `id` (which will be
+ undefined for new resources).
+ */
+ _url: function() {
+ var url = this.url,
+ id = this.get('id');
+
+ if (id !== undefined)
+ url += '/' + id;
+
+ return url;
+ }
+});
+
+/**
+ A controller for RESTful resources
+
+ Extend this class and define the following:
+
+ * `type` -- an Ember.Resource class; the class must have a `serialize` method that
+ returns a JSON representation of the object
+ * `url` -- (optional) the base url of the resource (e.g. '/contacts/active');
+ will default to the `url` for `type`
+*/
+Ember.ResourceController = Ember.ArrayController.extend({
+ type: Ember.required(),
+ content: [],
+
+ /**
+ Create and load a single `Ember.Resource` from JSON
+ */
+ load: function(json) {
+ var resource = this.get('type').create().deserialize(json);
+ this.pushObject(resource);
+ },
+
+ /**
+ Create and load `Ember.Resource` objects from a JSON array
+ */
+ loadAll: function(json) {
+ for (var i=0; i < json.length; i++)
+ this.load(json[i]);
+ },
+
+ /**
+ Replace this controller's contents with an ajax call to `url`
+ */
+ findAll: function() {
+ var self = this;
+
+ return jQuery.ajax({
+ url: this._url(),
+ dataType: 'json',
+ type: 'GET',
+ success: function(json) {
+ self.set("content", []);
+ self.loadAll(json);
+ }
+ });
+ },
+
+ /**
+ @private
+
+ Base URL for ajax calls
+
+ Will use the `url` set for this controller, or if that's missing,
+ the `url` specified for `type`.
+ */
+ _url: function() {
+ if (this.url === undefined)
+ return this.get('type').prototype.url;
+ else
+ return this.url;
+ }
+});
Please sign in to comment.
Something went wrong with that request. Please try again.