11 December 2013

Earlier I wrote about problems I had while trying to develop an Ember.js application with a Django REST framework-based backend. I did some research (I’ll get back to other results from that later) and tried using AngularJS for browser-side development, but it didn’t work out too well. I checked some other client-side frameworks but I really, really wanted to have a good model representation in the browser side code including relations between models and I couldn’t find one that felt right.

Eventually I decided to give it another go with Ember. I had an earlier semi-static UI mock that I extended using Ember and static fixtures. Which despite the steep learning curve eventually worked

great

well enough.

Though I could not postpone the dealing with the backend indefinitely.

I decided to ditch

1
ember-data-django-rest-adapter
completely, the main reason that I didn’t understand how I should format the backend response just by looking at the code (and no docs on that, unfortunately). It might be just the greatest thing since pre-buttered bread slices, but I just couldn’t understand how to get it working with the backend framework I was using even when it is by name supposed to work with it. Doh.

This is an after-the-fact reconstruction from memory on how I progressed:

  1. Attach a custom adapter based on

    1
    
    DS.JSONAdapter
    (e.g. set application’s
    1
    
    ApplicationAdapter
    value ).

  2. Try to understand what an adapter does and what a serializer does.

  3. Create a custom serializer. Wonder why some of the methods don’t get called. Realize that should have used

    1
    
    REST*
    base classes.

  4. Change adapter and serializer to back from

    1
    
    DS.RESTAdapter
    and
    1
    
    DS.RESTSerializer
    correspondigly.

  5. Hack hack hack …

Eventually I got an adapter and a serializer with only a small number of minor changes compared to the original

1
DS.REST*
versions:

  • Custom

    1
    
    extractSingle
    and
    1
    
    extractArray
    methods (which are called indirectly by
    1
    
    DS.RESTAdapter.extract
    ) that don’t look for subkeys, but use the payload value directly (as a direct value map, or an array of value maps, e.g.
    1
    
    [...]
    vs.
    1
    
    {"objects":[...]}
    ).

  • 1
    
    keyForAttribute
    and
    1
    
    keyForRelationship
    which turn Ember Data convention camelcase field names into underscored JSON data keys (from
    1
    
    instanceId
    to
    1
    
    instance_id
    ).

  • 1
    
    pathForType
    that doesn’t do pluralization of resource name (e.g.
    1
    
    project
    resource list is at
    1
    
    /project
    and individual resource at
    1
    
    /project/1
    ).

    (I still have to find a way to include the trailing slash in requests, Ember Data seems to be stripping them away, what causes extra redirects with Django REST framework. Or just specify

    1
    
    trailing_slash=False
    for the API router.)

And that’s it. Total size is about 20 LOC. I’m pretty surprised about that the minimal changes needed over

1
DS.REST*
classes. What I have not done is saving models to the backend — the code might be missing functionality to make that possible.

You can check the code out yourself at github. At the moment the client-side UI code is in

1
freezr/ui/static/freezr_ui/coffeescript
directory.

P.S. I had one major gotcha while doing this. I’ve documented that one in an another blog post.




blog comments powered by Disqus