1+ // ==========================================================================
2+ // Project: Ember Data Django Rest Adapter
3+ // Copyright: (c) 2013 Toran Billups http://toranbillups.com
4+ // License: MIT
5+ // ==========================================================================
6+
7+
8+ // v1.0.0
9+ // d45d071 (2014-01-08 21:19:17 -0600)
10+
11+
12+ ( function ( ) {
13+
14+ DS . DjangoRESTSerializer = DS . RESTSerializer . extend ( {
15+
16+ init : function ( ) {
17+ this . _super . apply ( this , arguments ) ;
18+ } ,
19+
20+ extractDjangoPayload : function ( store , type , payload ) {
21+ type . eachRelationship ( function ( key , relationship ) {
22+ if ( ! Ember . isNone ( payload [ key ] ) &&
23+ typeof ( payload [ key ] [ 0 ] ) !== 'number' &&
24+ typeof ( payload [ key ] [ 0 ] ) !== 'string' &&
25+ relationship . kind === 'hasMany' ) {
26+ if ( Ember . typeOf ( payload [ key ] ) === 'array' && payload [ key ] . length > 0 ) {
27+ var ids = payload [ key ] . mapBy ( 'id' ) ; //todo find pk (not always id)
28+ this . pushArrayPayload ( store , relationship . type , payload [ key ] ) ;
29+ payload [ key ] = ids ;
30+ }
31+ }
32+ else if ( ! Ember . isNone ( payload [ key ] ) && typeof ( payload [ key ] ) === 'object' && relationship . kind === 'belongsTo' ) {
33+ var id = payload [ key ] . id ;
34+ this . pushSinglePayload ( store , relationship . type , payload [ key ] ) ;
35+ payload [ key ] = id ;
36+ }
37+ } , this ) ;
38+ } ,
39+
40+ extractSingle : function ( store , type , payload ) {
41+ // using normalize from RESTSerializer applies transforms and allows
42+ // us to define keyForAttribute and keyForRelationship to handle
43+ // camelization correctly.
44+ this . normalize ( type , payload ) ;
45+ this . extractDjangoPayload ( store , type , payload ) ;
46+ return payload ;
47+ } ,
48+
49+ extractArray : function ( store , type , payload ) {
50+ var self = this ;
51+ for ( var j = 0 ; j < payload . length ; j ++ ) {
52+ // using normalize from RESTSerializer applies transforms and allows
53+ // us to define keyForAttribute and keyForRelationship to handle
54+ // camelization correctly.
55+ this . normalize ( type , payload [ j ] ) ;
56+ self . extractDjangoPayload ( store , type , payload [ j ] ) ;
57+ }
58+ return payload ;
59+ } ,
60+
61+ /**
62+ This method allows you to push a single object payload.
63+
64+ It will first normalize the payload, so you can use this to push
65+ in data streaming in from your server structured the same way
66+ that fetches and saves are structured.
67+
68+ @param {DS.Store } store
69+ @param {String } type
70+ @param {Object } payload
71+ */
72+ pushSinglePayload : function ( store , type , payload ) {
73+ type = store . modelFor ( type ) ;
74+ payload = this . extract ( store , type , payload , null , "find" ) ;
75+ store . push ( type , payload ) ;
76+ } ,
77+
78+ /**
79+ This method allows you to push an array of object payloads.
80+
81+ It will first normalize the payload, so you can use this to push
82+ in data streaming in from your server structured the same way
83+ that fetches and saves are structured.
84+
85+ @param {DS.Store } store
86+ @param {String } type
87+ @param {Object } payload
88+ */
89+ pushArrayPayload : function ( store , type , payload ) {
90+ type = store . modelFor ( type ) ;
91+ payload = this . extract ( store , type , payload , null , "findAll" ) ;
92+ store . pushMany ( type , payload ) ;
93+ } ,
94+
95+ /**
96+ Converts camelcased attributes to underscored when serializing.
97+
98+ Stolen from DS.ActiveModelSerializer.
99+
100+ @method keyForAttribute
101+ @param {String } attribute
102+ @returns String
103+ */
104+ keyForAttribute : function ( attr ) {
105+ return Ember . String . decamelize ( attr ) ;
106+ } ,
107+
108+ /**
109+ Underscores relationship names when serializing relationship keys.
110+
111+ Stolen from DS.ActiveModelSerializer.
112+
113+ @method keyForRelationship
114+ @param {String } key
115+ @param {String } kind
116+ @returns String
117+ */
118+ keyForRelationship : function ( key , kind ) {
119+ return Ember . String . decamelize ( key ) ;
120+ } ,
121+
122+ /**
123+ Underscore relationship names when serializing belongsToRelationships
124+
125+ @method serializeBelongsTo
126+ */
127+ serializeBelongsTo : function ( record , json , relationship ) {
128+ var key = relationship . key ;
129+ var belongsTo = record . get ( key ) ;
130+ var json_key = this . keyForRelationship ? this . keyForRelationship ( key , "belongsTo" ) : key ;
131+
132+ if ( Ember . isNone ( belongsTo ) ) {
133+ json [ json_key ] = belongsTo ;
134+ } else {
135+ if ( typeof ( record . get ( key ) ) === 'string' ) {
136+ json [ json_key ] = record . get ( key ) ;
137+ } else {
138+ json [ json_key ] = record . get ( key ) . get ( 'id' ) ;
139+ }
140+ }
141+
142+ if ( relationship . options . polymorphic ) {
143+ this . serializePolymorphicType ( record , json , relationship ) ;
144+ }
145+ } ,
146+
147+ /**
148+ Underscore relationship names when serializing hasManyRelationships
149+
150+ @method serializeHasMany
151+ */
152+ serializeHasMany : function ( record , json , relationship ) {
153+ var key = relationship . key ,
154+ json_key = this . keyForRelationship ( key , "hasMany" ) ,
155+ relationshipType = DS . RelationshipChange . determineRelationshipType (
156+ record . constructor , relationship ) ;
157+
158+ if ( relationshipType === 'manyToNone' ||
159+ relationshipType === 'manyToMany' )
160+ json [ json_key ] = record . get ( key ) . mapBy ( 'id' ) ;
161+ }
162+
163+ } ) ;
164+
165+
166+ } ) ( ) ;
167+
168+ ( function ( ) {
169+
170+ var get = Ember . get ;
171+
172+ DS . DjangoRESTAdapter = DS . RESTAdapter . extend ( {
173+ defaultSerializer : "DS/djangoREST" ,
174+
175+ /**
176+ Overrides the `pathForType` method to build underscored URLs.
177+
178+ Stolen from ActiveModelAdapter
179+
180+ ```js
181+ this.pathForType("famousPerson");
182+ //=> "famous_people"
183+ ```
184+
185+ @method pathForType
186+ @param {String } type
187+ @returns String
188+ */
189+ pathForType : function ( type ) {
190+ var decamelized = Ember . String . decamelize ( type ) ;
191+ return Ember . String . pluralize ( decamelized ) ;
192+ } ,
193+
194+
195+ createRecord : function ( store , type , record ) {
196+ var url = this . buildURL ( type . typeKey ) ;
197+ var data = store . serializerFor ( type . typeKey ) . serialize ( record ) ;
198+ return this . ajax ( url , "POST" , { data : data } ) ;
199+ } ,
200+
201+ updateRecord : function ( store , type , record ) {
202+ var data = store . serializerFor ( type . typeKey ) . serialize ( record ) ;
203+ var id = get ( record , 'id' ) ; //todo find pk (not always id)
204+ return this . ajax ( this . buildURL ( type . typeKey , id ) , "PUT" , { data : data } ) ;
205+ } ,
206+
207+ findMany : function ( store , type , ids , parent ) {
208+ var adapter , root , url , endpoint , attribute ;
209+ adapter = this ;
210+
211+ if ( parent ) {
212+ attribute = this . getHasManyAttributeName ( type , parent , ids ) ;
213+ endpoint = store . serializerFor ( type . typeKey ) . keyForAttribute ( attribute ) ;
214+ url = this . buildFindManyUrlWithParent ( type , parent , endpoint ) ;
215+ } else {
216+ Ember . assert ( "You need to add belongsTo for type (" + type . typeKey + "). No Parent for this record was found" ) ;
217+ }
218+
219+ return this . ajax ( url , "GET" ) ;
220+ } ,
221+
222+ ajax : function ( url , type , hash ) {
223+ hash = hash || { } ;
224+ hash . cache = false ;
225+
226+ return this . _super ( url , type , hash ) ;
227+ } ,
228+
229+ buildURL : function ( type , id ) {
230+ var url = this . _super ( type , id ) ;
231+
232+ if ( url . charAt ( url . length - 1 ) !== '/' ) {
233+ url += '/' ;
234+ }
235+
236+ return url ;
237+ } ,
238+
239+ buildFindManyUrlWithParent : function ( type , parent , endpoint ) {
240+ var root , url , parentValue ;
241+
242+ parentValue = parent . get ( 'id' ) ; //todo find pk (not always id)
243+ root = parent . constructor . typeKey ;
244+ url = this . buildURL ( root , parentValue ) ;
245+
246+ return url + endpoint + '/' ;
247+ } ,
248+
249+ /**
250+ Extract the attribute name given the parent record, the ids of the referenced model, and the type of
251+ the referenced model.
252+
253+ Given the model definition
254+
255+ ````
256+ App.User = DS.Model.extend({
257+ username: DS.attr('string'),
258+ aliases: DS.hasMany('speaker', { async: true})
259+ favorites: DS.hasMany('speaker', { async: true})
260+ });
261+ ````
262+
263+ with a model object
264+
265+ ````
266+ user1 = {
267+ id: 1,
268+ name: 'name',
269+ aliases: [2,3],
270+ favorites: [4,5]
271+ }
272+
273+ type = App.Speaker;
274+ parent = user1;
275+ ids = [4,5]
276+ name = getHasManyAttributeName(type, parent, ids) // name === "favorites"
277+ ````
278+
279+ @method getHasManyAttributeName
280+ @param {subclass of DS.Model } type
281+ @param {DS.Model } parent
282+ @param {Array } ids
283+ @returns String
284+ */
285+ getHasManyAttributeName : function ( type , parent , ids ) {
286+ var attributeName ;
287+ parent . eachRelationship ( function ( name , relationship ) {
288+ var relationshipIds ;
289+ if ( relationship . kind === "hasMany" && relationship . type . typeKey === type . typeKey ) {
290+ relationshipIds = parent . _data [ name ] . mapBy ( 'id' ) ;
291+ // check if all of the requested ids are covered by this attribute
292+ if ( Ember . EnumerableUtils . intersection ( ids , relationshipIds ) . length === ids . length ) {
293+ attributeName = name ;
294+ }
295+ }
296+ } ) ;
297+
298+ return attributeName ;
299+ }
300+
301+ } ) ;
302+
303+
304+ } ) ( ) ;
0 commit comments