Ember-Data: How to use `DS.Adapter.findHasMany`

前端 未结 4 1880
栀梦
栀梦 2021-02-06 01:36

UPDATE

Note that this question applies to Ember Data pre-1.0 beta, the mechanism for loading relationships via URL has changed significantly post-1.0 beta!


相关标签:
4条回答
  • 2021-02-06 02:12

    I got a small step closer to getting it working with revision 13 and based myself on sfossen's findHasMany implementation.

    For an Ember model 'Author' with a hasMany relationship 'blogPosts', my rest api looks like '/api/authors/:author_id/blog_posts'. When querying the rest api for an author with id 11 the blog_posts field reads '/authors/11/blog_posts'.

    I now see the related blog posts being returned by the server, but Ember still throws an obscure error that it can not read 'id' from an undefined model object when rendering the page. So I'm not quite there yet, but at least the related data is correctly requested from the rest service.

    My complete adapter:

    App.Adapter = DS.RESTAdapter.extend({
        url: 'http://localhost:3000',
        namespace: 'api',
        serializer: DS.RESTSerializer.extend({
            keyForHasMany: function(type, name) {
                return Ember.String.underscore(name);
            },
            extractHasMany: function(record, json, relationship) {
                var relationShip = relationship + '_path';
                return { url : json[relationShip] }
            }
        }),
        findHasMany: function(store, record, relationship, details) {
            var type = relationship.type;
            var root = this.rootForType(type);
            var url = this.url + '/' + this.namespace + details.url;
            var serializer = this.get('serializer');
    
            return this.ajax(url, "GET", {}).then(
                function(json) {
                    var relationship_key = Ember.String.underscore(relationship.key);
                    store.loadMany(type, json[relationship_key]);
                    var list = $.map(json[relationship_key], function(o){
                            return serializer.extractId(type, o);}
                    );
                    store.loadHasMany(record, relationship.key, list);
                }).then(null, $.rejectionHandler);
        }
    });
    
    0 讨论(0)
  • 2021-02-06 02:15

    Here is my solution but it is on Ember-data 0.14, so the world has moved on, even if we are still on this code base:

      findHasMany: function(store, record, relationship, details) {
        if(relationship.key !== 'activities') {
          return;
        }
    
        var type = relationship.type,
            root = this.rootForType(type),
            url = this.url + details.url,
            self = this;
    
        this.ajax(url, "GET", {
          data: {page: 1}
        }).then(function(json) {
          var data = record.get('data'),
            ids = [],
            references = json[relationship.key];
    
          ids = references.map(function(ref){
            return ref.id;
          });
    
          data[relationship.key] = ids;
    
          record.set('data', data);
    
          self.didFindMany(store, type, json);
          record.suspendRelationshipObservers(function() {
            record.hasManyDidChange(relationship.key);
          });
        }).then(null, DS.rejectionHandler);
      },
    

    I found replacing the data with the ids worked for me.

    0 讨论(0)
  • 2021-02-06 02:17

    Instead of an array of ids, the payload needs to contain "something else" than an array.

    In the case of the RESTAdapter, the returned JSON is like that:

    {blog: {id: 1, comments: [1, 2, 3]}
    

    If you want to handle manually/differently the association, you can return a JSON like that instead:

    {blog: {id: 1, comments: "/posts/1/comments"}
    

    It's up to your adapter then to fetch the data from the specified URL.

    See the associated test: https://github.com/emberjs/data/blob/master/packages/ember-data/tests/integration/has_many_test.js#L112

    0 讨论(0)
  • 2021-02-06 02:24

    I was glad to find this post, helped me. Here is my version, based off the current ember-data and your code.

    findHasMany: function(store, record, relationship, details) {
        var adapter = this;
        var serializer = this.get('serializer');
        var type = relationship.type;
        var root = this.rootForType(type);
        var url = (typeof(details) == 'string' || details instanceof String) ? details : this.buildURL(root);
        return this.ajax(url, "GET", {}).then(function(json) {
                adapter.didFindMany(store, type, json);
                var list = $.map(json[relationship.key], function(o){ return serializer.extractId(type, o);});
                store.loadHasMany(record, relationship.key, list);
            }).then(null, $.rejectionHandler);
    },
    

    for the reload issue, I did this, based on code I found in another spot, inside the serializer I overrode:

    materializeHasMany: function(name, record, hash, relationship) {
        var type = record.constructor,
                key = this._keyForHasMany(type, relationship.key),
                cache = record.cacheFor('data');
        if(cache) {
            var hasMany = cache.hasMany[relationship.key];
            if (typeof(hasMany) == 'object' || hasMany instanceof Object) {
                record.materializeHasMany(name, hasMany);
                return;
            }
        }
        var value = this.extractHasMany(type, hash, key);
        record.materializeHasMany(name, value);
    }
    

    I'm still working on figuring out paging, since some of the collections I'm working with need it.

    0 讨论(0)
提交回复
热议问题