Skip to content
master
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

#Emu Build Status

Emu is a simple data access library for Ember.js.

Breaking Changes

Breaking changes can be found here

To Start

// you need a store
App.Store = Emu.Store.extend({
  revision: 1
});

// lets define some models
App.Company = Emu.Model.extend({
	resourceName: "companies", //override default which would be 'companys'
	name: Emu.field("string"),
	address: Emu.field("App.Address", {partial: true}),
	employees: Emu.field("App.Employee", {collection: true, lazy: true})
});

App.Address = Emu.Model.extend({
	resourceName: "addresses",
	street: Emu.field("string"),
	town: Emu.field("string")
});

App.Employee = Emu.Model.extend({
	employeeId: Emu.field("string", {primaryKey: true}), //custom primary key, overrides default 'id' field
	name: Emu.field("string"),
	address: Emu.field("App.Address", {lazy: true})
});

Querying

var companies = App.Company.find({searchName: "inc", pageNumber: 3, recordCount: 20});
	//GET request to: 	http://www.mysite.com/companies?searchName=inc&pageNumber=3&recordCount=20

var companies = App.Company.find(function(company){return company.get("name").indexOf("inc") > 0;});
	//GET request to: 	http://www.mysite.com/companies
	//Filters results by function when collection has loaded

Partial loading

//Load a bunch of models - each model is "partially" loaded when getting as a collection
var companies = App.Company.find();
	//GET request to: 	http://www.mysite.com/companies
	//Response: [{id: 1, name: "Apple"}, {id: 2, name: "Facebook"}]

//Getting a partial value triggers a full load of the model
companies.get("firstObject.address");
	//GET request to:	http://www.mysite.com/companies/1
	//Response: {id: 1, name: "Apple", address: {street:"1 Infinite Loop", town: "Cupertino"}}

Lazy loading

//Get a lazy collection property
var members = company.get("employees");
	//GET request to:	http://www.mysite.com/companies/1/employees
	//Response: [{name: "Tom"}, {name: "Barny"}]
//Get a lazy model property
var address = employee.get("address");
	//GET request to:	http://www.mysite.com/employees/1/address

Persistence

//Save an existing model
var company = App.Company.find(5);
company.save();
	//PUT request to:	http://www.mysite.com/companies/5

//Save a new model
var company = App.Company.createRecord();
company.save();
	//POST request to:	http://www.mysite.com/companies

Default values

App.Foo = Emu.Model.extend({
	bar: Emu.field("string", {defaultValue: "moo"})
});

var foo = App.Foo.createRecord();
foo.get("bar"); // -> moo

Serialization

The default serializer creates a json representation of the object

App.FunnyPerson = Emu.Model.extend({
	firstName: Emu.field("string"),
	lastName: Emu.field("string")
});

will serialize to

{firstName:"Barry", lastName: "Chuckle"}

The serializer pluralizes type names by default. To turn this of set the pluralization flag to false:

App.Store = Emu.Store.extend({
  adapter: Emu.RestAdapter.extend({
    serializer: Emu.Serializer.extend({pluralization: false})
  })
})

To you can specify overrides in your models using a string or a function:

App.Person = Emu.Model.extend({
  resourceName: "people"
})

App.Person = Emu.Model.extend({
  resourceName: function(isSingular){
    return isSingular ? "person" : "people";
  }
})

If your backend prefers underscore seperated property names then you can easly switch the serializer when defining your store:

App.Store = Emu.Store.extend({
	adapter: Emu.RestAdapter.extend({
		serializer: Emu.UnderscoreSerializer.extend()
	})
})

which will serialize to

{first_name:"Paul", last_name: "Chuckle"}

This will also serialize the URLs with underscores

/funny_persons?search_term=chuckle

Receiving updates from server

You can receive updates from your server using the Emu.PushDataAdapter. There is currently a SignalR implementation of this. In order to use this you need to specify your adapter on the store.

Use SignalR adapter like this:

App.Store = Emu.Store.extend({
  pushAdapter: Emu.SignalrPushDataAdapter.extend({
    updatableTypes: ["App.RunningJob"]
  })
});

For this example the signalr adapter would look for a hub named 'runningJobHub' with an 'update' method.

You can then subcribe to updates for an object like this:

var runningJob = App.RunningJob.find(5);
runningJob.subscribeToUpdates();
runningJob.get("logMessages.firstObject.message"); // -> undefined
//updated received: {id: 5, logMessages: {id: 1, message: "something amazing happened"}}
runningJob.get("logMessages.firstObject.message"); // -> "something amazing happened"

You can also specify that you would like all children of a collection to receive updates when defining your model, like this:

App.Job = Emu.Model({
  title: Emu.field("string"),
  runningJobs: Emu.field("App.RunningJob", {collection: true, updatable: true})
});

You can also make your own PushDataAdapter like this:

App.MySpecialPushAdapter = Emu.PushDataAdapter.extend({
  //implement this function to receive updates for a type
  registerForUpdates: function(store, type){
    var _this = this;
    someCallbackThatReceivesAnUpdateForType(type, function(json){
      _this.didUpdate(type, store, json);
    });
  },

  //implement this function for any start code required
  start: function(store){
    this._super(store);
    //Initialization code here
  }
});

Model Events

You can subscribe to certain events on your models:

car.on("didStateChange", function(){ alert("hey don't touch that"); });

Available events are:

didStartLoading
didFinishLoading
didFinishPartialLoading
didStartSaving
didFinishSaving
didStateChange
didError

Model State

Models contain a few properties to describe their state:

isLoaded
isLoading
isSaving
isSaved
isDirty
isError

Pagination

You can load models as a paged collection:

var tweets = App.Tweet.findPaged(10);
	//GET request to: /tweets?pageNumber=1&pageSize=10
	//Response: {totalRecordCount: 10000, results: [{id: 1, content: "what a twit"},......]
tweets.loadMore();
	//GET request to: /tweets?pageNumber=2&pageSize=10
	//Response: {totalRecordCount: 10000, results: [{id: 11, content: "blah blah"},......]

You can also defined a paged collection as a field of another model:

App.Report = Emu.Model({
  title: Emu.field("string"),
  records: Emu.field("App.Record", {collection: true, paged: true})
});

App.Record = Emu.Model({
  year: Emu.field("number"),
  money: Emu.field("number")
});

var report = App.Report.find(5);
records = report.get("records");
	//GET request to: /reports/5/records?pageNumber=1&pageSize=250
	//Response: {totalRecordCount: 5000, results: [{id: 1, year: 1996, money: 1250},......]
records.get("length"); // -> 250
records.loadMore();
	//GET Request to: /reports/5/records?pageNumber=2&pageSize=250
	//Response: {totalRecordCount: 5000, results: [{id: 251, year: 2001, money: 12350},......]
records.get("length"); // -> 500

Get it

Builds can be found in the dist folder

Build it

bundle install
rakep

Test it

Install Karma

npm install -g karma

Run tests

cd emu
karma start

About

Simple data access library for Ember.js

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •