Search code examples
angularjsrestangular

How to model one-to-one relationships in AngularJS with Restangular


I have a companies collection with a country_id field that refers to _idin a countries collection.

Companies as follow:

{
    name: "acme",
    address: "zossener straße 123",
    postalCode: "10961",
    city: "berlin",
    country_id: "56d58d68ab68b5cf3f72788e"
}

Countries as follow:

{
    _id: "56d58d68ab68b5cf3f72788e",
    name: "Germany"
}

What I'm trying to do, is to replace the country_id of Companies to Countries.name. So for each company I want the country name, not the country ID. I'm using Restangular. My controller:

// creates a Restangular object of the 'companies' endpoint for later use
var Companies = Restangular.all('companies');

// for later pushing the countries
$scope.allCompanies = [];

// queries companies collection
Companies.getList().then(function(companies) {
  $scope.companies = companies;

  // iterates each company to get the country name
  for (var i = 0; i < $scope.companies.length; i++) {
    // prepares temp object to be pushed to $scope.allCompanies
    var buffer = {
      name: $scope.companies[i].name,
      address: $scope.companies[i].address,
      postalCode: $scope.companies[i].postalCode,
      city: $scope.companies[i].city,
      countryId: $scope.companies[i].country_id
    };

    // queries countries collection passing country_id
    var Country = Restangular.one('countries', $scope.companies[i].country_id);

    Country.get().then(function(country) {
      // sets country name for temp object based on country_id
      buffer.country = country.name;

      // pushes buffer to $scope.allCompanies
      $scope.allCompanies.push(buffer);
    });
  };

When running, $scope.allCompanies shows all companies with only one country, which is the last country assigned to buffer. I assume that there's something wrong with promises, but not sure. Any help? Thanks in advance.


Solution

  • You can wrap the logic that retrieves the country in a function. This way, the function keeps the correct reference of buffer without being affected by the change of i:

    // creates a Restangular object of the 'companies' endpoint for later use
    var Companies = Restangular.all('companies');
    
    // for later pushing the countries
    $scope.allCompanies = [];
    
    // queries companies collection
    Companies.getList().then(function(companies) {
      $scope.companies = companies;
       function setCountryName(buffer){
    
        // queries countries collection passing country_id
        var Country = Restangular.one('countries', buffer.countryId);
    
        Country.get().then(function(country) {
          // sets country name for temp object based on country_id
          buffer.country = country.name;
        });
        return buffer;
       }
    
      // iterates each company to get the country name
      for (var i = 0; i < $scope.companies.length; i++) {
        // prepares temp object to be pushed to $scope.allCompanies
        var buffer = {
          name: $scope.companies[i].name,
          address: $scope.companies[i].address,
          postalCode: $scope.companies[i].postalCode,
          city: $scope.companies[i].city,
          countryId: $scope.companies[i].country_id
        };
    
          // pushes buffer to $scope.allCompanies
          $scope.allCompanies.push(setCountryName(buffer));
      };