Skip to content
maherali edited this page Oct 6, 2011 · 25 revisions

A model is a class representing the business logic of your application. Models are subclasses of ISModel class. An ISModel instance has a dictionary of key/value object called attributes. You can add an attribute, clear it, or update it. When a model instance is represented by a server-backed instance, these attributes are populated from the server when you do fetch on the model instance.

For example, if you have a database table on the server called notes, a Note instance will represent a specific-row in the database to be used by the iOS client. If the notes table has three columns (title, body, and create_at), then when you fetch the model instance, the attributes dictionary will have three key/value entries, each for one of these column values.

Usually, server-backed applications utilize some sort of "id" column to uniquely identify a given row in a table. In this case, an "id" attribute is added to the attributes dictionary. By default, the "id" key is called id. However, you can change this behavior in your subclass of ISModel by overriding idAttribute method and returning the key value (e.g., @"name").

In your subclass, you can override the (NSDictionary*) defaults method to return default values of your model when it's created. The default behavior is to return nil.

Whatever you use for the "id" key, an id property is always present in the model instance and synchronized with the "id" attribute. A model instance is considered new if its id property is nil.

The method has:(NSString*) attr returns YES if the model instance has a attribue attr.

To retrieve the value for a given attribue, use get:(NSString*) attr. To remove an attribute, use unSet:(NSString*) attr.

Whenever a given attribute is changed (set, unset, updated), two events are triggered; one for the attribute and the other for the model itself. For example, if you change the value of the attribute name, a @"change:name" and @"change" events are triggered by the model instance. Other components of your app (such as views) can $watch() this model instance and update themselves accordingly.

Methods that change attributes take an optional second argument called options in the form of a dictionary. For example, here is the declaration of the set:withOptions method:

    - (ISModel*) set:(NSDictionary*) attrs withOptions:(NSDictionary*) options

The most important option is the silent option. Its key is SILENT_KEY. The 'IS_SILENT' macro is a convientient macro that helps you retrieve the truthiness of this option as shown below:

  BOOL silent = IS_SILENT(options);

If you pass in this key in the options of an operation (e.g., set) with the value YES, no errors are triggered nor any errors handlers are invoked (see discussion below).

A model can implement a validate: method. Whenever we change the attributes object of a given model, the validate: method is invoked. Inside this method, you can do some business-level validations. If this method returns an array of one or more errors, the change of attributes operation fails and either the ValidationErrorHandler is invoked (if present) or an "error" message is triggered by the model instance. You can access the array of errors from the triggered message using the ERRORS_KEY key in the notification of the $watch() block handler.

The ValidationErrorHandler that can be passed in the options of any method that changes the attributes and is invoked whenever the model fails the validation is decalared as follows:

    typedef void(^ValidationErrorHandler)(id origin, NSArray *errors, NSDictionary* options);

Whenever a model fails validation, it invokes this handler block passing itself as the origin, the errors array from the validate: as errors and the options in the original method invocation as options.

The following shows an example of a validate: method:

- (NSArray*) validate:(NSDictionary*) attrs{
    NSString    *title = [attrs objectForKey:@"title"];
    NSMutableArray  *arr = $marray();
    if(title && [title length] < 5){
        [arr addObject:@"Title cannot be less than 5 characters"];
    }
    return arr;
}

All model and collection instances have a unique client id that can be accessed by the cid property of the instance.

A model instance can belong to a collection instance. This linkage is maintained by the collection property of the model.

For a model that is server-backed, it needs to provide a url value. The url method, by default, looks to see if the model is inside a collection, if that's the case and the model is new, the collection's url' becomes the url value. If there is a collection and the model is not new, the collection's url' and the encoded value of the model's id value becomes the model's url. For example /notes/1 is the url value returned where /notes is the collection's url and 1 is the id value of the model instance.

If the model does not belong to a collection, then the value of its urlRoot method is substituted and used as above instead of the collection's url. Otherwise, an exception is thrown.

Clone this wiki locally