HipsterModel class
HipsterModel encapsulates individual records in your backend datastore. At its most concise, a model need only to implement the urlRoot method:
class ComicBook extends HipsterModel {
get urlRoot => '/comics';
}
class HipsterModel implements Hashable {
/** The internal representation of the record. */
Map attributes;
/**
* An [Events] object for the model. Any internal changes to the model will
* broadcast events from this object. See [ModelEvents] for the complete
* list of events supported.
*/
ModelEvents on;
/** If the model is part of a collection, it will be stored here. */
Collection collection;
/**
* If attributes is not supplied, it will be initalied to an empty
* [HashMap].
*/
HipsterModel([this.attributes]) {
on = new ModelEvents();
if (attributes == null) attributes = {};
}
// TODO: better hashing function (delimited keys and values?)
static String hash() {
return (new Date.now()).value.hashCode().toRadixString(16);
}
/**
* Convenience operator for attribute lookup:
*
* var comic = new ComicBook({'title': 'Superman'});
* comic['title'];
* // => 'Superman'
*/
operator [](attr) => attributes[attr];
/** The ID of the record in the backend store. */
get id => attributes['id'];
/**
* The URL at which creates or updates are stored. If the model has already
* been saved to the backend, then the ID will be appended
* (e.g. `/comics/42`).
*/
String get url => isSaved() ?
"$urlRoot/$id" : urlRoot;
/**
* The base URL for REST-like operations _without_ the trailing slash
* (e.g. `/comics`). This is delegated to the collection if present.
*
* If the subclass is ever used without a collection, then the subclass is
* required to define this:
* class ComicBook extends HipsterModel {
* get urlRoot => '/comics';
* }
*/
String get urlRoot => (collection == null) ?
"" : collection.url;
/**
* Returns true if the model has been _previously_ saved to the backend (not
* if the most recent changes have been saved).
*/
bool isSaved() => id != null;
/**
* Either creates or updates this record in the backend datastore. This
* method returns a [Future] that can be used to perform subsequent actions
* upon successful save:
* comic.
* save().
* then((_) { print("Yay! New comics!"); });
*/
Future<HipsterModel> save() {
Completer completer = new Completer();
String operation = isSaved() ? 'update' : 'create';
Future after_call = HipsterSync.call(operation, this);
after_call.
then((attrs) {
this.attributes = attrs;
on.load.dispatch(new ModelEvent('save', this));
completer.complete(this);
});
after_call.
handleException((e) {
completer.completeException(e);
return true;
});
return completer.future;
}
/**
* Instructs the backend datastore that this recored should be deleted. Upon
* successful removal, this method returns a [Future] that can be used to
* perform subsequent action:
* comic.
* delete.
* then((_) { print("Now I am sad.") });
*/
Future<HipsterModel> delete() {
Completer completer = new Completer();
HipsterSync.
call('delete', this).
then((attrs) {
var event = new ModelEvent('delete', this);
on.delete.dispatch(event);
completer.complete(this);
});
return completer.future;
}
}
Implements
Static Methods
String hash() #
static String hash() {
return (new Date.now()).value.hashCode().toRadixString(16);
}
Constructors
new HipsterModel([Map attributes]) #
If attributes is not supplied, it will be initalied to an empty
HashMap.
HipsterModel([this.attributes]) {
on = new ModelEvents();
if (attributes == null) attributes = {};
}
Properties
Map attributes #
The internal representation of the record.
Map attributes;
Collection collection #
If the model is part of a collection, it will be stored here.
Collection collection;
final int hashCode #
Get a hash code for this object.
All objects have hash codes. Hash codes are guaranteed to be the
same for objects that are equal when compared using the equality
operator ==. Other than that there are no guarantees about
the hash codes. They will not be consistent between runs and
there are no distribution guarantees.
If a subclass overrides hashCode it should override the
equality operator as well to maintain consistency.
abstract int get hashCode;
final id #
The ID of the record in the backend store.
get id => attributes['id'];
ModelEvents on #
An Events object for the model. Any internal changes to the model will
broadcast events from this object. See ModelEvents for the complete
list of events supported.
ModelEvents on;
final String url #
The URL at which creates or updates are stored. If the model has already
been saved to the backend, then the ID will be appended
(e.g. /comics/42).
String get url => isSaved() ? "$urlRoot/$id" : urlRoot;
final String urlRoot #
The base URL for REST-like operations without the trailing slash
(e.g. /comics). This is delegated to the collection if present.
If the subclass is ever used without a collection, then the subclass is required to define this:
class ComicBook extends HipsterModel {
get urlRoot => '/comics';
}
String get urlRoot => (collection == null) ? "" : collection.url;
Operators
operator [](attr) #
Convenience operator for attribute lookup:
var comic = new ComicBook({'title': 'Superman'});
comic['title'];
// => 'Superman'
operator [](attr) => attributes[attr];
Methods
Future<HipsterModel> delete() #
Instructs the backend datastore that this recored should be deleted. Upon
successful removal, this method returns a Future that can be used to
perform subsequent action:
comic.
delete.
then((_) { print("Now I am sad.") });
Future<HipsterModel> delete() {
Completer completer = new Completer();
HipsterSync.
call('delete', this).
then((attrs) {
var event = new ModelEvent('delete', this);
on.delete.dispatch(event);
completer.complete(this);
});
return completer.future;
}
bool isSaved() #
Returns true if the model has been previously saved to the backend (not if the most recent changes have been saved).
bool isSaved() => id != null;
Future<HipsterModel> save() #
Either creates or updates this record in the backend datastore. This
method returns a Future that can be used to perform subsequent actions
upon successful save:
comic.
save().
then((_) { print("Yay! New comics!"); });
Future<HipsterModel> save() {
Completer completer = new Completer();
String operation = isSaved() ? 'update' : 'create';
Future after_call = HipsterSync.call(operation, this);
after_call.
then((attrs) {
this.attributes = attrs;
on.load.dispatch(new ModelEvent('save', this));
completer.complete(this);
});
after_call.
handleException((e) {
completer.completeException(e);
return true;
});
return completer.future;
}