11/**
22 * API Bound Models for AngularJS
3- * @version v1.1.9 - 2015-05-07
3+ * @version v1.1.10 - 2015-10-24
44 * @link https://github.com/angular-platanus/restmod
55 * @author Ignacio Baixas <[email protected] > 66 * @license MIT License, http://www.opensource.org/licenses/MIT
@@ -1402,6 +1402,17 @@ RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {
14021402 this . $dispatch ( 'after-init' ) ;
14031403 } ,
14041404
1405+ /**
1406+ * @memberof RecordApi#
1407+ *
1408+ * @description Checks whether a record is new or not
1409+ *
1410+ * @return {boolean } True if record is new.
1411+ */
1412+ $isNew : function ( ) {
1413+ return this . $pk === undefined || this . $pk === null ;
1414+ } ,
1415+
14051416 /**
14061417 * @memberof RecordApi#
14071418 *
@@ -1412,7 +1423,7 @@ RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {
14121423 * @return {string } The resource partial url
14131424 */
14141425 $buildUrl : function ( _scope ) {
1415- return ( this . $pk === undefined || this . $pk === null ) ? null : Utils . joinUrl ( _scope . $url ( ) , this . $pk + '' ) ;
1426+ return this . $isNew ( ) ? null : Utils . joinUrl ( _scope . $url ( ) , this . $pk + '' ) ;
14161427 } ,
14171428
14181429 /**
@@ -1465,9 +1476,12 @@ RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {
14651476 * @return {RecordApi } this
14661477 */
14671478 $decode : function ( _raw , _mask ) {
1479+
1480+ Utils . assert ( _raw && typeof _raw == 'object' , 'Record $decode expected an object' ) ;
1481+
14681482 // IDEA: let user override serializer
14691483 this . $type . decode ( this , _raw , _mask || Utils . READ_MASK ) ;
1470- if ( this . $pk === undefined || this . $pk === null ) this . $pk = this . $type . inferKey ( _raw ) ; // TODO: warn if key changes
1484+ if ( this . $isNew ( ) ) this . $pk = this . $type . inferKey ( _raw ) ; // TODO: warn if key changes
14711485 this . $dispatch ( 'after-feed' , [ _raw ] ) ;
14721486 return this ;
14731487 } ,
@@ -1600,8 +1614,9 @@ RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {
16001614 . $dispatch ( 'before-update' , [ request , ! ! _patch ] )
16011615 . $dispatch ( 'before-save' , [ request ] )
16021616 . $send ( request , function ( _response ) {
1617+ if ( _response . data ) this . $unwrap ( _response . data ) ;
1618+
16031619 this
1604- . $unwrap ( _response . data )
16051620 . $dispatch ( 'after-update' , [ _response , ! ! _patch ] )
16061621 . $dispatch ( 'after-save' , [ _response ] ) ;
16071622 } , function ( _response ) {
@@ -1619,7 +1634,7 @@ RMModule.factory('RMRecordApi', ['RMUtils', function(Utils) {
16191634 . $dispatch ( 'before-save' , [ request ] )
16201635 . $dispatch ( 'before-create' , [ request ] )
16211636 . $send ( request , function ( _response ) {
1622- this . $unwrap ( _response . data ) ;
1637+ if ( _response . data ) this . $unwrap ( _response . data ) ;
16231638
16241639 // reveal item (if not yet positioned)
16251640 if ( this . $scope . $isCollection && this . $position === undefined && ! this . $preventReveal ) {
@@ -2020,15 +2035,14 @@ RMModule.factory('RMBuilder', ['$injector', 'inflector', '$log', 'RMUtils', func
20202035 */
20212036 function Builder ( _baseDsl ) {
20222037
2023- var mappings = {
2024- init : [ 'attrDefault' ] ,
2025- mask : [ 'attrMask' ] ,
2026- ignore : [ 'attrMask' ] ,
2027- map : [ 'attrMap' , 'force' ] ,
2028- decode : [ 'attrDecoder' , 'param' , 'chain' ] ,
2029- encode : [ 'attrEncoder' , 'param' , 'chain' ] ,
2030- 'volatile' : [ 'attrVolatile' ]
2031- } ;
2038+ var mappings = [
2039+ { fun : 'attrDefault' , sign : [ 'init' ] } ,
2040+ { fun : 'attrMask' , sign : [ 'ignore' ] } ,
2041+ { fun : 'attrMap' , sign : [ 'map' , 'force' ] } ,
2042+ { fun : 'attrDecoder' , sign : [ 'decode' , 'param' , 'chain' ] } ,
2043+ { fun : 'attrEncoder' , sign : [ 'encode' , 'param' , 'chain' ] } ,
2044+ { fun : 'attrVolatile' , sign : [ 'volatile' ] }
2045+ ] ;
20322046
20332047 // DSL core functions.
20342048
@@ -2113,10 +2127,7 @@ RMModule.factory('RMBuilder', ['$injector', 'inflector', '$log', 'RMUtils', func
21132127 extend : function ( _name , _fun , _mapping ) {
21142128 if ( typeof _name === 'string' ) {
21152129 this [ _name ] = Utils . override ( this [ name ] , _fun ) ;
2116- if ( _mapping ) {
2117- mappings [ _mapping [ 0 ] ] = _mapping ;
2118- _mapping [ 0 ] = _name ;
2119- }
2130+ if ( _mapping ) mappings . push ( { fun : _name , sign : _mapping } ) ;
21202131 } else Utils . extendOverriden ( this , _name ) ;
21212132 return this ;
21222133 } ,
@@ -2142,18 +2153,15 @@ RMModule.factory('RMBuilder', ['$injector', 'inflector', '$log', 'RMUtils', func
21422153 * @return {BuilderApi } self
21432154 */
21442155 attribute : function ( _name , _description ) {
2145- var key , map , args , i ;
2146- for ( key in _description ) {
2147- if ( _description . hasOwnProperty ( key ) ) {
2148- map = mappings [ key ] ;
2149- if ( map ) {
2150- args = [ _name , _description [ key ] ] ;
2151- for ( i = 1 ; i < map . length ; i ++ ) {
2152- args . push ( _description [ map [ i ] ] ) ;
2153- }
2154- args . push ( _description ) ;
2155- this [ map [ 0 ] ] . apply ( this , args ) ;
2156+ var i = 0 , map ;
2157+ while ( ( map = mappings [ i ++ ] ) ) {
2158+ if ( _description . hasOwnProperty ( map . sign [ 0 ] ) ) {
2159+ var args = [ _name ] ;
2160+ for ( var j = 0 ; j < map . sign . length ; j ++ ) {
2161+ args . push ( _description [ map . sign [ j ] ] ) ;
21562162 }
2163+ args . push ( _description ) ;
2164+ this [ map . fun ] . apply ( this , args ) ;
21572165 }
21582166 }
21592167 return this ;
@@ -2436,7 +2444,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
24362444 if ( _source || _url ) this . attrMap ( _attr , _source || _url ) ;
24372445
24382446 this . attrDecoder ( _attr , function ( _raw ) {
2439- this [ _attr ] . $reset ( ) . $decode ( _raw ) ;
2447+ this [ _attr ] . $reset ( ) . $decode ( _raw || [ ] ) ;
24402448 } )
24412449 . attrMask ( _attr , Utils . WRITE_MASK )
24422450 . attrMeta ( _attr , { relation : 'has_many' } ) ;
@@ -2497,7 +2505,7 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
24972505 if ( _source || _url ) this . attrMap ( _attr , _source || _url ) ;
24982506
24992507 this . attrDecoder ( _attr , function ( _raw ) {
2500- this [ _attr ] . $decode ( _raw ) ;
2508+ this [ _attr ] . $decode ( _raw || { } ) ; // TODO: null _raw should clear the object properties
25012509 } )
25022510 . attrMask ( _attr , Utils . WRITE_MASK )
25032511 . attrMeta ( _attr , { relation : 'has_one' } ) ;
@@ -3084,7 +3092,8 @@ RMModule.factory('RMModelFactory', ['$injector', '$log', 'inflector', 'RMUtils',
30843092 for ( i = 0 ; ( tmp = computes [ i ] ) ; i ++ ) {
30853093 Object . defineProperty ( self , tmp [ 0 ] , {
30863094 enumerable : true ,
3087- get : tmp [ 1 ]
3095+ get : tmp [ 1 ] ,
3096+ set : function ( ) { }
30883097 } ) ;
30893098 }
30903099 }
@@ -3499,6 +3508,8 @@ RMModule.factory('RMPackerCache', [function() {
34993508RMModule . factory ( 'RMSerializer' , [ '$injector' , 'inflector' , '$filter' , 'RMUtils' , function ( $injector , inflector , $filter , Utils ) {
35003509
35013510 function extract ( _from , _path ) {
3511+ if ( _from === null && _path . length > 1 ) return undefined ;
3512+
35023513 var node ;
35033514 for ( var i = 0 ; _from && ( node = _path [ i ] ) ; i ++ ) {
35043515 _from = _from [ node ] ;
@@ -3526,9 +3537,10 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
35263537 mappings = { } ,
35273538 vol = { } ;
35283539
3529- function isMasked ( _name , _mask ) {
3540+ function isMasked ( _name , _mask , _ctx ) {
35303541 if ( typeof _mask === 'function' ) return _mask ( _name ) ;
35313542 var mask = masks [ _name ] ;
3543+ if ( typeof mask === 'function' ) mask = mask . call ( _ctx ) ; // dynamic mask
35323544 return ( mask && ( mask === true || mask . indexOf ( _mask ) !== - 1 ) ) ;
35333545 }
35343546
@@ -3541,7 +3553,7 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
35413553 if ( maps ) {
35423554 for ( i = 0 , l = maps . length ; i < l ; i ++ ) {
35433555 fullName = prefix + maps [ i ] . path ;
3544- if ( isMasked ( fullName , _mask ) ) continue ;
3556+ if ( isMasked ( fullName , _mask , _ctx ) ) continue ;
35453557
35463558 if ( maps [ i ] . map ) {
35473559 value = extract ( _from , maps [ i ] . map ) ;
@@ -3577,7 +3589,7 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
35773589
35783590 fullName = prefix + decodedName ;
35793591 // prevent masked or already mapped properties to be set
3580- if ( mapped [ fullName ] || isMasked ( fullName , _mask ) ) continue ;
3592+ if ( mapped [ fullName ] || isMasked ( fullName , _mask , _ctx ) ) continue ;
35813593
35823594 value = decodeProp ( _from [ key ] , fullName , _mask , _ctx ) ;
35833595 if ( value !== undefined ) _to [ decodedName ] = value ; // ignore value if filter returns undefined
@@ -3589,7 +3601,7 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
35893601 var filter = decoders [ _name ] , result = _value ;
35903602
35913603 if ( filter ) {
3592- result = filter . call ( _ctx , _value ) ;
3604+ result = filter . call ( _ctx , _value , _mask ) ;
35933605 } else if ( typeof _value === 'object' ) {
35943606 // IDEA: make extended decoding/encoding optional, could be a little taxing for some apps
35953607 if ( isArray ( _value ) ) {
@@ -3615,7 +3627,7 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
36153627 if ( _from . hasOwnProperty ( key ) && key [ 0 ] !== '$' ) {
36163628 fullName = prefix + key ;
36173629 // prevent masked or already mapped properties to be copied
3618- if ( mapped [ fullName ] || isMasked ( fullName , _mask ) ) continue ;
3630+ if ( mapped [ fullName ] || isMasked ( fullName , _mask , _ctx ) ) continue ;
36193631
36203632 value = encodeProp ( _from [ key ] , fullName , _mask , _ctx ) ;
36213633 if ( value !== undefined ) {
@@ -3632,7 +3644,7 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
36323644 if ( maps ) {
36333645 for ( var i = 0 , l = maps . length ; i < l ; i ++ ) {
36343646 fullName = prefix + maps [ i ] . path ;
3635- if ( isMasked ( fullName , _mask ) ) continue ;
3647+ if ( isMasked ( fullName , _mask , _ctx ) ) continue ;
36363648
36373649 value = _from [ maps [ i ] . path ] ;
36383650 if ( ! maps [ i ] . forced && value === undefined ) continue ;
@@ -3653,7 +3665,7 @@ RMModule.factory('RMSerializer', ['$injector', 'inflector', '$filter', 'RMUtils'
36533665 var filter = encoders [ _name ] , result = _value ;
36543666
36553667 if ( filter ) {
3656- result = filter . call ( _ctx , _value ) ;
3668+ result = filter . call ( _ctx , _value , _mask ) ;
36573669 } else if ( _value !== null && typeof _value === 'object' && typeof _value . toJSON !== 'function' ) {
36583670 // IDEA: make deep decoding/encoding optional, could be a little taxing for some apps
36593671 if ( isArray ( _value ) ) {
@@ -3915,7 +3927,7 @@ RMModule.factory('DefaultPacker', ['restmod', 'inflector', 'RMPackerCache', func
39153927 return restmod . mixin ( function ( ) {
39163928 this . define ( 'Model.unpack' , function ( _resource , _raw ) {
39173929 var name = null ,
3918- links = this . getProperty ( 'jsonLinks' , 'linked ' ) ,
3930+ links = this . getProperty ( 'jsonLinks' , 'included ' ) ,
39193931 meta = this . getProperty ( 'jsonMeta' , 'meta' ) ;
39203932
39213933 if ( _resource . $isCollection ) {
0 commit comments