1
- Astro . eventManager . on ( 'initDefinition' , function ( schemaDefinition ) {
2
- var Class = this ;
1
+ // Prototype Methods ///////////////////////////////////////////////////////////
3
2
4
- if ( _ . has ( schemaDefinition , 'relations' ) ) {
5
- Class . addRelations ( schemaDefinition . relations ) ;
3
+ var prototypeMethods = { } ;
4
+
5
+ prototypeMethods . getRelated = function ( relationName ) {
6
+ var doc = this ;
7
+ var Class = doc . constructor ;
8
+
9
+ // If there is already a reference to the relation object(s) stored in the
10
+ // "_references" object then we can take it without looking in collection.
11
+ if ( _ . has ( this . _references , relationName ) ) {
12
+ return this . _references [ relationName ] ;
13
+ }
14
+
15
+ // Look for the relation definition.
16
+ var relation = Class . getRelation ( relationName ) ;
17
+ if ( ! relation ) {
18
+ return ;
19
+ }
20
+
21
+ // Get a collection defined in the relation.
22
+ var ForeignClass = Astro . getClass ( relation . class ) ;
23
+ var ForeignCollection = ForeignClass . getCollection ( ) ;
24
+
25
+ // Prepare selector to select only these documents that much the relation.
26
+ var selector = { } ;
27
+ var localValue = this . get ( relation . local ) ;
28
+ selector [ relation . foreign ] = _ . isArray ( localValue ) ?
29
+ { $in : localValue } : localValue ;
30
+
31
+ // Get a related object.
32
+ var related ;
33
+ if ( relation . type === 'one' ) {
34
+ related = ForeignCollection . findOne ( selector ) ;
35
+ } else if ( relation . type === 'many' ) {
36
+ related = ForeignCollection . find ( selector ) ;
37
+ }
38
+
39
+ // Assing the related object to the "_references" object for further use.
40
+ return this . _references [ relationName ] = related ;
41
+ } ;
42
+
43
+ // Class Methods ///////////////////////////////////////////////////////////////
44
+
45
+ var classMethods = { } ;
46
+
47
+ classMethods . hasRelation = function ( relationName ) {
48
+ return _ . has ( this . schema . relations , relationName ) ;
49
+ } ;
50
+
51
+ classMethods . getRelation = function ( relationName ) {
52
+ return this . schema . relations [ relationName ] ;
53
+ } ;
54
+
55
+ classMethods . getRelations = function ( ) {
56
+ return this . schema . relations ;
57
+ } ;
58
+
59
+ // Class Events ////////////////////////////////////////////////////////////////
60
+
61
+ var classEvents = { } ;
62
+
63
+ classEvents . beforeInit = function ( ) {
64
+ var doc = this ;
65
+
66
+ doc . _references = { } ;
67
+ } ;
68
+
69
+ classEvents . afterSave = function ( ) {
70
+ this . _references = { } ;
71
+ } ;
72
+
73
+ // onInitDefinition ////////////////////////////////////////////////////////////
74
+
75
+ Astro . eventManager . on (
76
+ 'initDefinition' , function onInitDefinitionRelations ( schemaDefinition ) {
77
+ var Class = this ;
78
+ var schema = Class . schema ;
79
+ var relationsDefinitions = { } ;
80
+
81
+ if ( _ . has ( schemaDefinition , 'relations' ) ) {
82
+ if ( ! _ . isObject ( schemaDefinition . relations ) ) {
83
+ throw new Error (
84
+ 'The relations definition in the "' + Class . getName +
85
+ '" class has to be an object'
86
+ ) ;
87
+ }
88
+
89
+ _ . each ( schemaDefinition . relations , function ( relation , relationName ) {
90
+ var relation ;
91
+
92
+ if ( ! _ . isObject ( relation ) ) {
93
+ throw new Error (
94
+ 'The "' + relationName + '" relation definition in the "' +
95
+ Class . getName + '" class has to be an object'
96
+ ) ;
97
+ }
98
+
99
+ if ( relation . type !== 'one' && relation . type !== 'many' ) {
100
+ throw new Error (
101
+ 'The relation type for the "' + relationName +
102
+ '" relation in the "' + this . getName ( ) +
103
+ '" class should be "one" or "many"'
104
+ ) ;
105
+ }
106
+
107
+ relationsDefinitions [ relationName ] = relation ;
108
+ } ) ;
109
+ }
110
+
111
+ if ( _ . size ( relationsDefinitions ) > 0 ) {
112
+ // Add relations to the schema.
113
+ schema . relations = schema . relations || { } ;
114
+ _ . extend ( schema . relations , relationsDefinitions ) ;
115
+
116
+ var methods = { } ;
117
+ _ . each ( relationsDefinitions , function ( relationDefinition , relationName ) {
118
+ methods [ relationName ] = function ( ) {
119
+ return this . getRelated ( relationName ) ;
120
+ } ;
121
+ } ) ;
122
+
123
+ // Add events only if the class has any relations.
124
+ Class . extend ( {
125
+ events : classEvents ,
126
+ methods : methods
127
+ } ) ;
128
+
129
+ // Add methods to the class prototype if it has any relations.
130
+ _ . extend ( Astro . BaseClass . prototype , prototypeMethods ) ;
131
+
132
+ // Add class methods to the class if it has any relations.
133
+ _ . extend ( Class , classMethods ) ;
134
+ }
6
135
}
7
- } ) ;
136
+ ) ;
0 commit comments