ФорумПрограммированиеJavaScriptAngularJS → Подскажите кошерный способ связывания данных при использовании $resource

Подскажите кошерный способ связывания данных при использовании $resource

  • adw0rd

    Сообщения: 22902 Репутация: N Группа: в ухо

    Spritz 27 февраля 2015 г. 12:11

    Допустим у меня есть три модели

    User
      - email
      - password
    
    Currency
      - name
      - code
    
    Account
      - user_id ForeignKey User
      - currency_id ForeignKey Currency
      - amount
    

    (как видно, последняя модель ссылается на первые две)

    Далее, я по отдельности подгружаю данные

    var myServices = angular.module('myServices', ['ngResource']);
    myServices.factory('User', ['$resource', function ($resource) {
        return $resource('/api/user', {}, {'query': {method: 'GET', isArray: true}});
    }]);
    myServices.factory('Currency', ['$resource', function ($resource) {
        return $resource('/api/currency', {}, {'query': {method: 'GET', isArray: true}});
    }]);
    myServices.factory('Account', ['$resource', function ($resource) {
        return $resource('/api/account', {}, {'query': {method: 'GET', isArray: true}});
    }]);
    

    После чего, хочу пользоваться вот так

    function MyCtrl(Account) {
        this.accounts = Account.query();
    }
    
    ‹html›
        ‹body ng-app›
            ‹ul ng-controller="MyCtrl"›
                ‹li ng-repeat="account in accounts"›
                    {{ account.user.email }} - {{ account.currency.code }} 
                ‹/li›
            ‹/ul›
        ‹/body›
    ‹/html›
    

    Как такого добится, без явного перебора всех аккаунтов в контроллере или сервисе и маппинга?

    @Абырвалг, @andrey.lastochkin.96, @Ivan.

    adw/0
  • Ivan.

    Сообщения: 494 Репутация: N Группа: Адекваты

    Spritz 27 февраля 2015 г. 12:36, спустя 24 минуты 32 секунды

    Ну во первых работать не должен твой код, потому что контроллер называется MyCtrl, а обращаешься к $scope
    ‹ul ng-controller="MyCtrl as main"›
    ‹li ng-repeat="account in main.accounts"›
    {{ account.user.email }} - {{ account.currency.code }}
    ‹/li›
    ‹/ul›
    ‹/body›


    И собственно не понял в чем твоя проблема - возвращай с сервера ответ в таком виде, в котором тебе нужно. $resource это же просто обертка по сути для REST-API, указать что там именно результат другого ресурса во первых нельзя, во вторых незачем. Или ты в ресурсы еще какие-то кастомные методы хочешь засунуть?

    {+++23+++}
    А блин, читаю с конца)

    {+++58+++}
    Я бы вернул просто ID-шники и замапил

    {+++48+++}
    А, ну да, можно еще делать users[account.user].email
  • adw0rd

    Сообщения: 22902 Репутация: N Группа: в ухо

    Spritz 27 февраля 2015 г. 12:47, спустя 11 минут 40 секунд

    Ну во первых работать не должен твой код, потому что контроллер называется MyCtrl, а обращаешься к $scope

    @Ivan., да это вообще был псевдокод)

    Спустя 274 сек.

    Я бы вернул просто ID-шники и замапил

    @Ivan., да вот мапать то ручками не хочется, хочется что-то типа:

    myServices.factory('Account', ['User', 'Currency', $resource', function (User, Currency, $resource) {
        return $resource('/api/account', {}, {
            'query': {method: 'GET', isArray: true},
            'relations': {'user_id': (User, 'id'), 'currency_id': (Currency, 'id')}
        });
    }]);
    

    в итоге, если с сервера приходит поле "user_id", то он берет прикешированный User и вытаскивает оттуда по "id" данные и вставляет в "account.user"

    adw/0
  • adw0rd

    Сообщения: 22902 Репутация: N Группа: в ухо

    Spritz 27 февраля 2015 г. 12:59, спустя 11 минут 52 секунды

    Побыстрому так сделал, завтра подумаю как пропатчить $resource

    function getRelation(items, field, value) {
        return items.filter(function (item) { return item[field] == value })[0];
    }
    
    function MyCtrl($scope, Account) {
        var vm = this;
        Account.query().$promise.then(function (items) {
            vm.accounts = items.map(function (obj) {
                obj.user = getRelation($scope.users, 'id', obj.user_id);
                obj.currency = getRelation($scope.currencies, 'id', obj.currency_id);
                return obj;
            });
        });
    }
    
    adw/0
  • kostyl

    Сообщения: 5199 Репутация: N Группа: Джедаи

    Spritz 27 февраля 2015 г. 15:21, спустя 2 часа 21 минуту 24 секунды

    @Абырвалг, @andrey.lastochkin.96, @Ivan.

    @adw0rd, вызываешь ))
  • andrey.lastochkin.96

    Сообщения: 10 Репутация: N Группа: Адекваты

    Spritz 27 февраля 2015 г. 15:25, спустя 4 минуты 27 секунд

    Сервис по-правильному должен возвращать подготовленные данные.

    НО, если тебе все же это приходит, и ты ничего не можешь с этим сделать, тогда надо готовить данные в бизнес-логике (модели).
    В mithril (в angular есть аналог) я бы сделал примерно так:

    this.data = [];
    m.sync([users, currencies, accounts])
    .then(() => prepareData())

Пожалуйста, авторизуйтесь, чтобы написать комментарий!