      1 // ==========================================================================
      2 // Project:   The M-Project - Mobile HTML5 Application Framework
      3 // Copyright: (c) 2010 M-Way Solutions GmbH. All rights reserved.
      4 // Creator:   Sebastian
      5 // Date:      18.11.2010
      6 // License:   Dual licensed under the MIT or GPL Version 2 licenses.
      7 //            http://github.com/mwaylabs/The-M-Project/blob/master/MIT-LICENSE
      8 //            http://github.com/mwaylabs/The-M-Project/blob/master/GPL-LICENSE
      9 // ==========================================================================
     10
     11 m_require('core/utility/logger.js');
     12
     13 /**
     14  * @class
     15  *
     16  * M.ModelAttribute encapsulates all meta information about a model record's property:
     17  * * is it required?
     18  * * what data type is it of? (important for mapping to relational database schemas)
     19  * * what validators shall be applied
     20  * All M.ModelAttributes for a model record are saved under {@link M.Model#__meta} property of a model.
     21  * Each ModelAttribute is saved with the record properties name as key.
     22  * That means:
     23  *
     24  * model.record[propA] is the value of the property.
     25  * model.__meta[propA] is the {@link M.ModelAttribute} object for the record property.
     26  *
     27  * @extends M.Object
     28  */
     29 M.ModelAttribute = M.Object.extend(
     30 /** @scope M.ModelAttribute.prototype */ {
     31
     32     /**
     33      * The type of this object.
     34      *
     35      * @type String
     36      */
     37     type: 'M.ModelAttribute',
     38
     39     /**
     40      * The data type for the model record property.
     41      * Extremely important e.g. to map model to relational database table.
     42      *
     43      * @type String
     44      */
     45     dataType: null,
     46
     47     /**
     48      * Indicates whether this property is required to be set before persisting.
     49      * If YES, then automatically @link M.PresenceValidator is added to the property, to check the presence.
     50      *
     51      * @type Boolean
     52      */
     53     isRequired: NO,
     54
     55     /**
     56      * Array containing all validators for this model record property.
     57      * E.g. [@link M.PresenceValidator, @link M.NumberValidator]
     58      * @type Object
     59      */
     60     validators: null,
     61
     62     /**
     63      * Iterates over validators array and calls validate on each validator with the param object passed to the validator.
     64      * @param {Object} obj The parameter object containing the model id, the record as M.ModelAttribute object and the value of the property.
     65      * @returns {Boolean} Indicates wheter the property is valid (YES|true) or invalid (NO|false).
     66      */
     67     validate: function(obj) {
     68         var isValid = YES;
     69         for (var i in this.validators) {
     70             if(!this.validators[i].validate(obj)) {
     71                isValid = NO;
     72             }
     73         }
     74         return isValid;
     75     }
     76 });
     77
     78 //
     79 // CLASS METHODS
     80 //
     81
     82 /**
     83  * Returns a model attribute.
     84  *
     85  * @param dataType The data type of the attribute: e.g. String
     86  * @param opts options for the attribute, such as defaultValue, isRequired flag, etc. ...
     87  * @returns {Object} {@link M.ModelAttribute} object
     88  */
     89 M.ModelAttribute.attr = function(dataType, opts) {
     90     if (!opts) {
     91         opts = {};
     92     }
     93     if (!opts.dataType) {
     94         opts.dataType = dataType || 'String';
     95     }
     96
     97     /* if validators array is not set and attribute is required, define validators as an empty array, (this is for adding M.PresenceValidator automatically */
     98     if (!opts.validators && opts.isRequired) {
     99         opts.validators = [];
    100     }
    101
    102     /* if model attribute is required, presence validator is automatically inserted */
    103     if (opts.isRequired) {
    104         /* check if custom presence validator has been added to validators array, if not add the presence validator*/
    105         if( _.select(opts.validators, function(v){return v.type === 'M.PresenceValidator'}).length === 0) {
    106             opts.validators.push(M.PresenceValidator);
    107         }
    108     }
    109     return this.extend(opts);
    110 };