jeudi 22 juin 2017

Action Cables, nested JSON attributes and JSONAPI

I have a fairly specific problem that I was hoping one of you really intelligent folk might know a solution for (or even a workaround at this stage)

Specifically, I'm dealing with action cables, nested JSON, and the JSONAPI.

I have an asset model, which has some attributes like name, desc etc. but it also has an attribute called state which is a complex nested JSON object.

// app/models/asset.js
export default DS.Model.extend({
    // Attributes
    name: DS.attr('string'),
    desc: DS.attr('string'),
    state: DS.attr(),
    lastSeen: DS.attr('date'),
});

When anything on the asset changes in the backend, it is pushed down the cable to Ember, where it does a pushPayload(data), the payload looks like this;

{
    "data": {
        "id": "5",
        "type": "assets",
        "attributes": {
            "asset_id": "962ABC",
            "name": "962 ABC",
            "desc": "Test Vehicle",
            "activation_status": "active",
            "state": {
                "avl": {
                    "longitude": 152.9475426,
                    "reported_at": "2017-06-22T21:59:52Z"
                },
                "dfm": {
                    "in_alarm": false,
                    "reported_at": "2017-06-21T05:46:57Z",
                    "sensitivity": "normal",
                    "voice_prompt": false,
                    "driver_detected": true,
                },
                "tpms": {
                    "system_desc": "Doran 360MTR",
                    "system_type": "doran360mtr"
                }
            },
            "last_seen": "2017-06-22T21:59:54.000Z"
        },
        "relationships": {
            "company": {
                "data": {
                    "id": "1",
                    "type": "companies"
                }
            },
            "events": {
                "links": {
                    "related": "/events/?asset_id=5"
                }
            },
            "messages": {
                "links": {
                    "related": "/messages/?asset_id=5"
                }
            }
        }
    }
}

This all works fine and dandy, updates to the asset & state are displayed as they happen thanks to the cable, and state is read only so I don't have to worry about saving anything. HOWEVER, I have noticed that when any single attribute on state changes in the backend, the entire asset is pushed down from the backend (this should be fine), and then this fires the observer for state and also all observers for state descendants - whereas I need it to only fire the observer for the state attribute that changed.

I have tried a number of things and each seemed to either not work at all, or still continue to update state in a way that fired off all state observers.

What I have tried;

  1. ember-model-data-fragments (while it should work, I think the way that the action cable pushes the data must subvert this?)
  2. embedded records (requires an ID for state, not currently compatible with JSONAPI)
  3. raw json transform (making the json into ember objects, didn't seem to help)

Can anyone suggest a strategy or solution for me to try? I've spent nearly 2 days on this problem.. I would even settle for just splitting it up between avl/tpms/dfm, as long as when an attribute in one of those sections is changed, it doesn't notify properties from the other 2 sections.

Thanks




Aucun commentaire:

Enregistrer un commentaire