2013-11-14 5 views
12

Допустим, мы имеемКак перезагрузить асинхронный со ссылками hasMany отношения?

Post = DS.Model.extend({ 
    comments: DS.hasMany({async: true}) 
}) 

Comment = DS.Model.extend({ 
    post: DS.belongsTo() 
}) 

, и я должен использовать функцию links, потому что в противном случае я получаю ошибку 414 из-за слишком большого количества комментариев на пост.

С этой фиксации https://github.com/emberjs/data/commit/4d717bff53f8c93bedbe74e7965a4f439882e259

Похоже, что это невозможно, чтобы вызвать перезагрузку post.get («комментарии»), т.е. отправки запроса GET на, например пост/42/комментариев.

Есть ли решение для этого?

+0

Я думаю, что лучший способ решить эту проблему, чтобы переопределить 'update' метод из' RecordArray', в классе 'ManyArray'. И дайте некоторый контекст, как «ссылки». В настоящий момент использование 'comments.update()' будет извлекать все комментарии, введя только «post/1/comments». Но для этого потребуется какой-то запрос на растяжение. –

+0

Да, в качестве первой попытки я попытался использовать метод обновления;). Я бы хотел услышать @wycats в этом предложении PR. –

+0

Было ли это представлено как PR? – claptimes

ответ

7

Благодаря @igorT это реализовано. https://github.com/emberjs/data/pull/2297

Теперь у ManyArray есть метод reload(), который вы даже можете вызвать, если отношение еще не загружено.

Вы можете увидеть некоторые варианты, читая tests

1

я была такая же проблема, и я изменял найти «решение»

я создал компонент «CommentLoader». Этот компонент принимает один аргумент (post_id) и перед «inserting» (willInsertElement). Я обрабатываю все комментарии и обрабатываю их. он работает, но ... я не горжусь этим :(

+0

Что вы подразумеваете под «grad all comments»? Вы создаете пользовательский запрос ajax в файле willInsertElement, например $ .ajax ('/ comments? Post_id = 42')? –

+0

i предназначенный для захвата: Я использовал queryparmas (this.store.find ('comment', {post_id: params.post_id}) – hkairi

+0

Хорошо, это должно работать, но, к сожалению, оно не заботится о вещах «ссылок». для того, чтобы дать некоторое время об этом. Думаю, я соглашусь ответить @ marcio-rodrigues-correa-junior. –

15

UPDATE

Как @ sly7_7 сказал в своем ответе ниже, эта функция теперь доступен в Ember-данных. Таким образом, если вы используете версия 1.0.0-beta.11 или выше, этот код не нужен

Вы можете снова открыть ManyArray и создать новый метод под названием reloadLinks() с следующим образом:.

var get = Ember.get; 

DS.ManyArray.reopen({ 
    reloadLinks: function() { 
     var records = get(this, 'content'), 
     store = get(this, 'store'), 
     owner = get(this, 'owner'), 
     type = get(this, 'type'), 
     name = get(this, 'name'), 
     resolver = Ember.RSVP.defer(); 

     var meta = owner.constructor.metaForProperty(name); 
     meta.type = type; 
     var link = owner._data.links[meta.key]; 
     store.findHasMany(owner, link, meta, resolver); 
    } 
}); 

использование я S следующее:

comments.reloadLinks(); 

Дайте посмотреть в этой скрипкой http://jsfiddle.net/H6Gqf/

+0

Это действительно интересно, и я думаю, что он мог бы сделать эту работу на данный момент :) Один комментарий, хотя мне кажется странным должны дать атрибутName, поскольку сама функция находится на соответствующем многомерном. Я думаю, что можно получить его с некоторым отражением на множестве массивов? –

+0

Я не нашел способ сделать это. Когда создается множество массивов [здесь] (https://github.com/emberjs/data/blob/e7996c4dc5248360466c1f330fde6f5455bb3ca4/packages/ember-data/lib/system/store.js#L576), у нас есть тип и владелец, но не имя свойства, и нам нужно имя свойства. В вашем случае bacause post имеет только одну связь с комментарием, возможно, можно идентифицировать отношения. В другой ситуации, когда модель имеет две связи одного типа, как узнать, что такое ток? Посмотрите, что прокомментировал код http://jsfiddle.net/marciojunior/E2Auc/ –

+0

Кажется, что у ManyArray есть свойство 'name', которое именно вы ищете. Или, может быть, я что-то упустил. см. http://jsfiddle.net/mVxzn/2/ –

0

Другой вариант заключается в добавлении метода к модели. Следует также работать hasMany:

search: DS.belongsTo('search', {async: true}) 

updateSearch: -> 
    resolver = Ember.RSVP.defer() 
    resolver.resolve = => 
    # do something after promise resolves 
    relationship = @constructor.metaForProperty('search') 
    link = @_data.links[relationship.key] 
    @store.findBelongsTo this, link, relationship, resolver 
2

Перезарядка hasMany не встроен непосредственно в Ember данных пока нет, но это на своем пути. Для решения, которое я использую, требуется Ember Data 1.0b9 + canary, который включает opt-in coalesced finds.

Шаг 1: Входите.

Я выбрал уровень ApplicationAdapter, но вы можете сделать это на основе адаптера для каждой модели. Вот что у меня есть:

MyApp.ApplicationAdapter = DS.ActiveModelAdapter.extend({ 
    coalesceFindRequests: true 
}); 

Чтобы дать вам представление о том, почему это важно и хорошо, одна странице на нашем приложении было видеть 50+ запросов до этого изменения. Мы теперь видим только 11. Это все еще не здорово, но это одно из улучшений!

Шаг 2: Перезарядка Записи в Ассоциации

я просто завернуть перевалку в зависимости от моей модели, так:

MyApp.SomeModel = DS.Model.extend({ 
    fooMany: DS.hasMany('foo', { async: true }), 
    barMany: DS.hasMany('bar', { async: true }), 
    bazOne: DS.belongsTo('baz', { async: true }), 

    reloadAssociated: function() { 
    var foosPromises = this.get('foos').invoke('reload'), 
     barsPromises = this.get('bars').invoke('reload'), 
     bazPromise = this.get('baz').reload(); 

    return Em.RSVP.hash({ 
     foos: foosPromises, 
     bars: barsPromises, 
     baz: bazPromise 
    }); 
    } 
}); 

Я признаю, что это не очень красиво, но это лучшее решение, которое я придумал до тех пор, пока перезагрузка не будет построена непосредственно в ассоциациях.

1

С ember-data-1.0.0-beta.10 Я использую следующее расширение модели.

Просто позвоните model.reloadRelationship(name), где name - это имя атрибута модели, представляющего отношение.

Это работает как для нормального, так и для связи принадлежит отношениям/hasMany.

DS.Model.reopen({ 
    reloadRelationship: function(name) { 
     var meta = this.constructor.metaForProperty(name), 
      link = this._data.links ? this._data.links[meta.key] : null; 
     if (!link) { 
      if (meta.kind === 'belongsTo') { 
       this.get(name).then(function(model) { model.reload(); }); 
      } else { 
       this.get(name).invoke('reload'); 
      } 
     } else { 
      meta.type = this.constructor.typeForRelationship(name); 
      if (meta.kind === 'belongsTo') { 
       this.store.findBelongsTo(this, link, meta); 
      } else { 
       this.store.findHasMany(this, link, meta); 
      } 
     } 
    } 
}); 

Единственное, что здесь отсутствует некоторые проверки, например, проверить, если модель уже перегрузки, когда модель перезагружается с помощью ссылки или чеком, чтобы увидеть, если имя свойства существует в текущей модели.

EDIT уголек-данные 1.0.0-beta.14:

DS.Model.reopen({ 
    reloadRelationship: function(key) { 
     var record = this._relationships[key]; 
     if (record.relationshipMeta.kind === 'belongsTo') { 
      return this.reloadBelongsTo(key); 
     } else { 
      return this.reloadHasMany(key); 
     } 
    }, 
    reloadHasMany: function(key) { 
     var record = this._relationships[key]; 
     return record.reload(); 
    }, 
    reloadBelongsTo: function(key) { 
     var record = this._relationships[key]; 
     if (record.link) { 
      return record.fetchLink(); 
     } else { 
      record = this.store.getById(record.relationshipMeta.type, this._data[key]); 
      return record.get('isEmpty') ? this.get(key) : record.reload(); 
     } 
    } 
}); 

HasMany отношение будет Откат к родному методу перезагрузки.

Для отношений BelongsTo он сначала проверяет, нужно ли перезагружать запись (если она еще не загружена до этого момента, она вызовет вызов только для получения записи, иначе она вызовет перезагрузку).

Смежные вопросы