Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API enhancement: get full route for nested resource #736

Open
donaldpipowitch opened this issue Jun 4, 2014 · 8 comments
Open

API enhancement: get full route for nested resource #736

donaldpipowitch opened this issue Jun 4, 2014 · 8 comments

Comments

@donaldpipowitch
Copy link

If I use nested resources I sometimes have to deal with generic route names. Say I have a users and companies route and both have a nested resource address, which I can operate on with users/:id/address and companies/:id/address.

Now I want to enhance the restangularized element with custom logic inside Restangular.setOnElemRestangularized, but I need to treat the address of a user differently than the address of a company. I can't just look into the route param, because it is address in both cases. I need to check elem.parentResource.route, too. It could look like this:

Restangular.setOnElemRestangularized(function(elem, isCollection, route) {
  if(elem.parentResource.route + '/' + route === 'companies/address') { /* do stuff */ }
  if(elem.parentResource.route + '/' + route === 'users/address') { /* do stuff */ }
});

This can become quite verbose and error prone. It becomes even worse with deeper nested resources or in more generic situations where I have to make sanity checks (e.g. is elem.parentResource defined?).

It would be very useful to get the full route of a resource like this:

Restangular.setOnElemRestangularized(function(elem, isCollection, route) {
  if(elem.getFullRoute() === 'companies/address') { /* do stuff */ }
  if(elem.getFullRoute() === 'users/address') { /* do stuff */ }
});

.getFullRoute() would basically recursively prepend every existing parentResource.route separated by a /. elem.getFullRoute() would be equal to elem.route for every non-nested resource.

function getFullRoute(elem) {
  var parentRoute = '';
  if(elem.parentResource) {
    parentRoute = getFullRoute(elem.parentResource) + '/';
  }
  return parentRoute + elem.route;
}

What do you think?

@bendalton
Copy link

I found this issue while looking for a way to do Restangular.extendModel(...) with a route like 'clubs/members'. I haven't tried yet, but I would love to see the preferred syntax of the extendModel/extendCollection methods to be compatible.

@oneironautics
Copy link

Just ran into this issue, too. extendModel and extendCollection are effectively useless in the scenario I'm in due to the all or nothing nature of how routes are extended. /user/detail and /customer/detail, for instance.

@joshrieken
Copy link

+1

1 similar comment
@Rodeoclash
Copy link

+1

@wkoffel
Copy link

wkoffel commented Oct 9, 2014

I too am running into this.
Looking for a good way to extendModel() on a nested resource. In my case, I have:

myApp.factory 'Gallery', (Restangular) ->
  Restangular.service('galleries')

Gallery.one(id).getList("photos")

and I'd like to have all the returned photo objects extended. I tried extending it with the galleries route, but never managed to extend the photo model properly:

  Restangular.extendModel 'galleries/:id/photos', (model) ->
    model.testFunc = (msg) ->
      console.log(msg)
    model

@vincentdieltiens
Copy link

I ran into the same issue. I have customers/contacts and suppliers/contacts which are different.

The next solution seems to work well :

  1. Define the getFullRoute method (this is an iterative version. don't know if recursive whould be better)
function getFullRoute(elem) {
  var currentElem = elem
  var fullRoute = [];

  do {
    fullRoute.splice(0, 0, currentElem.route);
    currentElem = currentElem.parentResource;
  }
  while(currentElem !== null);

  return fullRoute.join('/');
}
  1. Add line to config.transformElem to get the full route of the element
    and try to get the transformers of the full route before getting the transformers of the route.
config.transformElem = function(elem, isCollection, route, Restangular, force) {
    if (!force && !config.transformLocalElements && !elem[config.restangularFields.fromServer]) {
      return elem;
    }

    var fullRoute = getFullRoute(elem);
    var typeTransformers = config.transformers[fullRoute] || config.transformers[route];
    var changedElem = elem;
    if (typeTransformers) {
        _.each(typeTransformers, function(transformer) {
           changedElem = transformer(isCollection, changedElem);
        });
    }
    return config.onElemRestangularized(changedElem,
      isCollection, route, Restangular);
};

With that small changes, extendModel will work like this :

Restangular.extendModel('customers/contacts', function(model) {
  // ...
});
Restangular.extendModel('suppliers/contacts', function(model) {
  // ...
});

What do you think ?

@vincentdieltiens
Copy link

My solution can be found at : https://github.com/vincentdieltiens/restangular

@end-user
Copy link

This issue is still open and still seems relevant. Is there a workaround or a fix? How can I apply custom methods to nested model objects?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants