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; }