ember.js, How do I load related models while loadi

2019-08-17 01:33发布

问题:

I'm ember.js newbie and facing daily problems :-)

Today's problem is my server backend doesn't support sideloading. (If I understood 'sideload' right, it is server returns related models at once with multiple JSON root)

for example, my server only returns below per request:

for /api/v1/posts.json

{
  posts: [{
    id: 91,
    title: "ember.js"
  }, {
    id: 81,
    title: "ember-data.js"
  }]
}

for /api/v1/comments.json

{
  comments: [{
    id: 928,
    postId: 91,
  }, {
    id: 927,
    postId: 92,
  }]
}

When I load post model, go /#/posts, the view didnot render comment but if I load comment manually by typing URL of comment route in location bar, /#/comments, and go back, the comments are displayed properly.

so I just try like this, in post route, (third line)

App.PostsRoute = Ember.Route.extend({
  model: function(params) {
    this.store.find('comment');
    return this.store.find('post');
  }
})

and it works! (load and populate comment too!) but I think it is not right way.

Is there any good or RIGHT way to do this?

Edit -- Add model definitions

My post model is something like:

App.Post = DS.Model.extend({
  title: DS.attr('string'),
  content: DS.attr('string'),
  comments: DS.hasMany('comment', {async: true}),
})

and comment model is:

App.Account = DS.Model.extend({
  content: DS.attr('string'),
  post: DS.belongsTo('post'),
})

I do not use ember-cli and started from ember-starter-kit and watching some tutorials from homepage and web.

And, I use custom Adapter because My backend, in fack, does not support ember style JSON response and I cannot touch it:

App.SpinAdapter = DS.ActiveModelAdapter.extend({
  host: 'http://spin.example.com:8080',
  namespace: 'api/v1',

  init: function() {
    this._super();
    console.log('SpinAdapter...');
  }
});

App.SpinSerializer = DS.ActiveModelSerializer.extend({
  extract: function(store, type, payload, id, requestType) {
    console.log('SpinSezer#extract...' + type + '/' + id + '/' + requestType);
    return payload;
  },
});

App.PostAdapter = App.SpinAdapter.extend({});
App.PostSerializer = App.SpinSerializer.extend({});

App.CommentAdapter = App.SpinAdapter.extend({});
App.CommentSerializer = App.SpinSerializer.extend({});

回答1:

I found the answer while I am think more after I edit the question!

the problem is overrided extract method. (details on my prev. question, Can I use normal (rails default) JSON response on Ember Data?)

when I override whole extract, as answer on the question, I found that some method(s) was not called. (maybe _super.extract does more other things.) so I just tested with per model extract with minimal overriding and call super. and it works!

changed extract methods are:

App.SpinAdapter = DS.ActiveModelAdapter.extend({
  host: 'http://spin.example.com:8080',
  namespace: 'api/v1',

  init: function() {
    this._super();
    console.log('SpinAdapter...');
  }
});

App.SpinSerializer = DS.ActiveModelSerializer.extend({
  extract: function(store, type, payload, id, requestType) {
    console.log('SpinSezer#extract...' + type + '/' + id + '/' + requestType);
    return this._super(store, type, payload, id, requestType);
  },
});

App.PostAdapter = App.SpinAdapter.extend({});
App.PostSerializer = App.SpinSerializer.extend({
  extract: function(store, type, payload, id, requestType) {
    return this._super(store, type, {posts: payload}, id, requestType);
  },
});

App.CommentAdapter = App.SpinAdapter.extend({});
App.CommentSerializer = App.SpinSerializer.extend({
  extract: function(store, type, payload, id, requestType) {
    return this._super(store, type, {comments: payload}, id, requestType);
  },
});

Problem is solved. but sadly, since the response of posts has no entry about comments, (Database and API structure is "only child knows their parent") If I load post first, then related comments are not loaded. solution of half.

I just tried with nested routes and hope to load nested URL automatically, but it is not happen. :-(