Ember adapter - Passing link from adapter to serializer?


#1

I have an adapter set up for a database of prices. Often the price range includes null values at the beginning because there is no data in that range. I want to check for this and may need to do another query to get the first value.

At the moment I’ve overwritten my urlForQueryRecord and urlForQuery to get the initial data.

I thought I could use links in the serializer normalize function but my response doesn’t include the query options needed. Is there are a way to pass the link from the adapter where I have that data?


#2

My api doesn’t include an id either. I’d like to create one from the query options.

Maybe I shouldn’t even be using ember-data but taking advantage of serializers seems like a great idea.


#3

I’ve searched through the source code. I can override the adapter handleResponse() and set an attribute to it’s return value which is sent to the serializer payload, unfortunately the query property from queryRecord is not available there.

That data stops at the ajax function. If only the code would pass on the options argument to the requestData variable below, I could then accept that in handleResponse…

  ajax(url, type, options) {
let token = heimdall.start('adapter.ajax');
let adapter = this;

let requestData = {
  url:    url,
  method: type
};
....

I don’t know how to override that whole ajax function and pass along the values because it returns a promise which gets resolved somewhere else in the store.

The request url is available in the handleResponse function which I could pass along with the payload. I can scrape the values out of it, seems like a backwards way to do things.


#4

Generally I find when I hit these types of major headaches with what I’m trying to do, it’s because I’m thinking at cross-purposes to what the framework defaults to.

If we take a step back, it sounds like you have a model of some kind that may or may not have some price data available when you first retrieve it. If it doesn’t, then you would need to retrieve the related prices (either immediately or down the road). Is that an accurate summary?

If so, have you considered splitting your price data out into a related model and making it a hasMany relationship? That would seem to resolve most of the problems you are hitting …


#5

Thanks for the thoughts.

I don’t know if a hasMany relationship is ideal.

I have a database (influx) that uses SQL type queries. I was hoping I could make a model+adapter that would interface in a simple way:

queryRecord('chart', { timeFrame: '7d', marketName: 'USD', groupBy: '1h' } )

The json response is always: { results: { series: [0]: data: { pricevalues } } }`

There’s never a model name or id I can use.

I was able to pass the initial query data to the serializer by overriding the adapter ajax function, resolving the promise then creating another.

  ajax(url, type, options) {
    let response = this._super(...arguments);
    return new RSVP.Promise(function(resolve) {
      response.then(r => {
        r.options = options;
        resolve(r);
      })
    });
  },

Using the “links” attribute in the serializer doesn’t work to get the first value I needed because it looks for a model named ‘results’ returned by the query json data.

After all this I think making a util and skipping all the adapter/serializer stuff is better suited.

I’m trying to work with the framework, but it’s hard when I can’t see where things fit.


#6

Hmm, if that’s what you’re after, what you might want to do is use a custom serializer to map the data back as you’d want. You could then do something akin to this as a model:

// app/models/chart.js

import DS from 'ember-data';

export default DS.Model.extend({
  data: DS.attr()
});

and this as your serializer:

// app/serializers/chart.js
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  normalizeQueryRecordResponse(store, primaryModelClass, payload, id, requestType) {
    return {
      id, // might need to auto-generate this?
      type: requestType
      data: {
        data: payload.results.series[0].data
      }
    }
  }
});

Believe that should get you started down the right track?