ngResource, разрешающий вложенные ресурсы

Какие варианты существуют для разрешения вложенных ресурсов в ответах ngResource?

Были некоторые связанные вопросы о разрешении конечных точек для вложенного ресурса в ngResource, но этот вопрос касается случаев, когда ответ REST содержит второй ресурс, вложенный в запрашиваемую коллекцию, особенно сопоставления 1-к-1, где у вас не было бы например pets/<id>/owner как собственный ресурс.

Скажем, есть два ресурса, Pets и Owners:

ПОЛУЧИТЬ /домашние животные:

[{
  name: 'spark',
  type: 'dog',
  owner: '/owners/3/' # alternatively just '3' or the full object.
}]

Как разработчик, я иногда хочу запросить ресурс Owner в целом, иногда я хочу запросить ресурс Pet, а затем я хочу автоматически преобразовать атрибут owner в экземпляр ресурса.

Это мое текущее решение:

.factory('Pet', function ($resource, Owner) {
  var Pet = $resource('/pets/:id', {id: '@id'});

  Pet.prototype.getOwner = function () {
    return new Owner(this.owner); // or Owner.get({id: this.owner})
  }

  return Pet;
})

Проблем тут много. Есть целостность - для одного. Я считаю, что эта реализация позволяет использовать несколько экземпляров одного и того же ресурса. Тогда есть практичность. У вас также есть дополнительные атрибуты для отслеживания (owner и getOwner(), а не только owner; возможно, setOwner, если вы хотите иметь возможность сохранить модель).

Альтернативное решение может быть построено на transformResponse, но было бы хаком включать его в каждый ресурс, имеющий вложенное сопоставление.


person lyschoening    schedule 16.10.2013    source источник


Ответы (2)


Я считаю, что именно поэтому Мартин Гонтовникас создал Restangular. Ему не нравилось иметь дело с вложенными $resources в основном фреймворке angular. Я думаю, что его решение Restangular прекрасно впишется в ваши потребности. Его код находится на GitHub здесь, и у него есть хорошее вступительное видео на YouTube здесь.

Проверьте это. Я думаю, вы обнаружите, что он делает именно то, что вы хотите.

person tennisgent    schedule 16.10.2013
comment
Итак, что вы можете сделать в Restangular, так это вызвать Restangular.one('pets', 1).one('owner').get() и загрузить /pets/1/owner. Я ищу парадигму, в которой есть одна уникальная конечная точка для каждого ресурса, поэтому каждый владелец будет доступен только из /owners/, но в то же время это может быть можно встроить объект в ответ для другого ресурса. - person lyschoening; 17.10.2013
comment
Прямоугольный способ выглядит следующим образом: pet.owner = Restangular.restangularizeElement(pet, pet.owner, 'owners'). - person lyschoening; 17.10.2013
comment
Это больше похоже на два зависимых ресурса, а не на действительно вложенные ресурсы. вложенный будет означать, что один доступен изнутри (имеется в виду некоторый производный URL-адрес) другого. Наличие двух отдельных ресурсов (Pet и Owner), которые зависят друг от друга, — это другое дело. У вас есть доступ к серверной службе? Кажется, что зависимости были бы лучше, если бы бэкэнд предварительно заполнил другую зависимость... но это может быть невозможно - person tennisgent; 17.10.2013
comment
Я имею в виду вложенные, буквально вложенные в ответный JSON-объект, например, когда у вас есть внешний ключ к другому ресурсу (как показано в моем примере выше). Это не обязательно должны быть детско-родительские отношения. - person lyschoening; 18.10.2013

Обновление: я немного поработал над этим и начал новый модуль angular , доступный на GitHub. Ответ ниже касается Сути, которую я написал изначально.

Похоже, там нет ничего похожего на то, что я искал. Я начал реализацию решения, которое поддерживает только операции get и getList (запрос). Добавление остальных методов должно быть тривиальным, поскольку я в значительной степени сохранил макет модуля ngResource. Суть моей реализации ниже.

https://gist.github.com/lyschoening/7102262

Ресурсы могут быть встроены в JSON либо как полные объекты, которые просто оборачивают в правильную модель Resource, либо как URI, которые разрешаются автоматически. В дополнение к встроенным ресурсам модуль также поддерживает типичные вложенные ресурсы, либо как настоящие родительско-дочерние коллекции (где ресурс доступен только после выбора родителя), либо как коллекции с перекрестными ссылками.

Yard = Resource('/yard')     # resource model
Yard.$nested('trees')        # embedded item or list of items

Chair = Resource('/chair')

Yard.$nested('/chair')      # sub-collection without its own model
                             # (for many-to-many)

Tree = Resource('/tree')

# child-collection with its own model
TreeHouse = Tree.$childResource('/treehouse')


yard = Yard.get(1)
# GET /yard/1
# {
#    "uri": "/yard/1",
#    "trees": [
#       "/tree/15",   -- reference, looked-up automatically with GET
#       {"uri": "/tree/16", "name": "Apple tree"} 
#                     -- full object, resolved to Tree instance
#    ]
# }
# GET /tree/16
# {"uri": "/tree/15", "name": "Pine tree"}

yard.chair.getList()
# GET /yard/1/chair
# [{"uri": "/chair/1", ...}, ..]
# -- model inferred from URI

yard.trees[0].treehouse.getList()
# GET /tree/15/treehouse
# [{"uri": "/tree/15/treehouse/1", ...}, ..]
# -- automatically resolved to TreeHouse instance
person lyschoening    schedule 22.10.2013
comment
Где угловой модуль? Вы удалили его? - person bruno; 12.11.2015
comment
@bruno Исправлена ​​ссылка ; это не совсем то же самое, что и в исходном комментарии, так как это зависит от json-refs. В настоящее время я больше не поддерживаю это, так как планирую переписать его на TypeScript для Angular 2. Он предназначен для использования с Фляжное зелье. Чтобы ознакомиться с ядром логики разрешения ссылок, ознакомьтесь с этой сутью. - person lyschoening; 12.11.2015