22
33RMModule . factory ( 'RMBuilderRelations' , [ '$injector' , 'inflector' , '$log' , 'RMUtils' , 'restmod' , 'RMPackerCache' , function ( $injector , inflector , $log , Utils , restmod , packerCache ) {
44
5+ // wraps a hook callback to give access to the $owner object
6+ function wrapHook ( _fun , _owner ) {
7+ return function ( ) {
8+ var oldOwner = this . $owner ;
9+ this . $owner = _owner ;
10+ try {
11+ return _fun . apply ( this , arguments ) ;
12+ } finally {
13+ this . $owner = oldOwner ;
14+ }
15+ } ;
16+ }
17+
18+ // wraps a bunch of hooks
19+ function applyHooks ( _target , _hooks , _owner ) {
20+ for ( var key in _hooks ) {
21+ if ( _hooks . hasOwnProperty ( key ) ) {
22+ _target . $on ( key , wrapHook ( _hooks [ key ] , _owner ) ) ;
23+ }
24+ }
25+ }
26+
527 /**
628 * @class RelationBuilderApi
729 *
@@ -27,15 +49,23 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
2749 * @param {string } _url Partial url
2850 * @param {string } _source Inline resource alias (optional)
2951 * @param {string } _inverseOf Inverse property name (optional)
52+ * @param {object } _params Generated collection default parameters
53+ * @param {object } _hooks Hooks to be applied just to the generated collection
3054 * @return {BuilderApi } self
3155 */
32- attrAsCollection : function ( _attr , _model , _url , _source , _inverseOf ) {
56+ attrAsCollection : function ( _attr , _model , _url , _source , _inverseOf , _params , _hooks ) {
57+
58+ var options , globalHooks ; // global relation configuration
3359
3460 this . attrDefault ( _attr , function ( ) {
3561
3662 if ( typeof _model === 'string' ) {
3763 _model = $injector . get ( _model ) ;
3864
65+ // retrieve global options
66+ options = _model . getProperty ( 'hasMany' , { } ) ;
67+ globalHooks = options . hooks ;
68+
3969 if ( _inverseOf ) {
4070 var desc = _model . $$getDescription ( _inverseOf ) ;
4171 if ( ! desc || desc . relation !== 'belongs_to' ) {
@@ -45,25 +75,23 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
4575 }
4676 }
4777
48- var self = this ,
49- scope = this . $buildScope ( _model , _url || inflector . parameterize ( _attr ) ) ,
50- col = _model . $collection ( null , scope ) ;
78+ var scope = this . $buildScope ( _model , _url || inflector . parameterize ( _attr ) ) , col ; // TODO: name to url transformation should be a Model strategy
5179
52- // TODO: there should be a way to modify scope behavior just for this relation,
53- // since relation item scope IS the collection, then the collection should
54- // be extended to provide a modified scope. For this an additional _extensions
55- // parameters could be added to collection, then these 'extensions' are inherited
56- // by child collections, the other alternative is to enable full property inheritance ...
80+ // setup collection
81+ col = _model . $collection ( _params || null , scope ) ;
82+ if ( globalHooks ) applyHooks ( col , globalHooks , this ) ;
83+ if ( _hooks ) applyHooks ( col , _hooks , this ) ;
84+ col . $dispatch ( 'after-has-many-init' ) ;
5785
5886 // set inverse property if required.
5987 if ( _inverseOf ) {
88+ var self = this ;
6089 col . $on ( 'after-add' , function ( _obj ) {
6190 _obj [ _inverseOf ] = self ;
6291 } ) ;
6392 }
6493
6594 return col ;
66- // simple support for inline data, TODO: maybe deprecate this.
6795 } ) ;
6896
6997 if ( _source || _url ) this . attrMap ( _attr , _source || _url ) ;
@@ -87,15 +115,22 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
87115 * @param {string } _url Partial url (optional)
88116 * @param {string } _source Inline resource alias (optional)
89117 * @param {string } _inverseOf Inverse property name (optional)
118+ * @param {object } _hooks Hooks to be applied just to the instantiated record
90119 * @return {BuilderApi } self
91120 */
92- attrAsResource : function ( _attr , _model , _url , _source , _inverseOf ) {
121+ attrAsResource : function ( _attr , _model , _url , _source , _inverseOf , _hooks ) {
122+
123+ var options , globalHooks ; // global relation configuration
93124
94125 this . attrDefault ( _attr , function ( ) {
95126
96127 if ( typeof _model === 'string' ) {
97128 _model = $injector . get ( _model ) ;
98129
130+ // retrieve global options
131+ options = _model . getProperty ( 'hasOne' , { } ) ;
132+ globalHooks = options . hooks ;
133+
99134 if ( _inverseOf ) {
100135 var desc = _model . $$getDescription ( _inverseOf ) ;
101136 if ( ! desc || desc . relation !== 'belongs_to' ) {
@@ -105,10 +140,13 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
105140 }
106141 }
107142
108- var scope = this . $buildScope ( _model , _url || inflector . parameterize ( _attr ) ) ,
109- inst = _model . $new ( null , scope ) ;
143+ var scope = this . $buildScope ( _model , _url || inflector . parameterize ( _attr ) ) , inst ;
110144
111- // TODO: provide a way to modify scope behavior just for this relation
145+ // setup record
146+ inst = _model . $new ( null , scope ) ;
147+ if ( globalHooks ) applyHooks ( inst , globalHooks , this ) ;
148+ if ( _hooks ) applyHooks ( inst , _hooks , this ) ;
149+ inst . $dispatch ( 'after-has-one-init' ) ;
112150
113151 if ( _inverseOf ) {
114152 inst [ _inverseOf ] = this ;
@@ -325,8 +363,8 @@ RMModule.factory('RMBuilderRelations', ['$injector', 'inflector', '$log', 'RMUti
325363 } ;
326364
327365 return restmod . mixin ( function ( ) {
328- this . extend ( 'attrAsCollection' , EXT . attrAsCollection , [ 'hasMany' , 'path' , 'source' , 'inverseOf' ] ) // TODO: rename source to map, but disable attrMap if map is used here...
329- . extend ( 'attrAsResource' , EXT . attrAsResource , [ 'hasOne' , 'path' , 'source' , 'inverseOf' ] )
366+ this . extend ( 'attrAsCollection' , EXT . attrAsCollection , [ 'hasMany' , 'path' , 'source' , 'inverseOf' , 'params' , 'hooks' ] ) // TODO: rename source to map, but disable attrMap if map is used here...
367+ . extend ( 'attrAsResource' , EXT . attrAsResource , [ 'hasOne' , 'path' , 'source' , 'inverseOf' , 'hooks' ] )
330368 . extend ( 'attrAsReference' , EXT . attrAsReference , [ 'belongsTo' , 'key' , 'prefetch' ] )
331369 . extend ( 'attrAsReferenceToMany' , EXT . attrAsReferenceToMany , [ 'belongsToMany' , 'keys' ] ) ;
332370 } ) ;
0 commit comments