• 
      

    Fix link generation for extension web API resources

    Review Request #3082 — Created April 25, 2012 and submitted

    Information

    Djblets

    Reviewers

    This change adds the Web API resources defined in an extension's `resources` attribute to the link tree. Now each resource will be added to the 'links' dictionary of the extension resource, and in the list of extensions. These links will only appear when the extension is enabled.
    
    Also fixed is improper generation of the resource URLs. The URLs were generated with the wrong attribute, causing them to use underscores instead of dashes.
    Tested with my new extension's resources, and the extensions with resources found here: https://github.com/mikeconley/RB-Toy-Extensions
    Description From Last Updated

    Managers, no, but unless an extension has its own ExtensionManager, there will only be one. (Maybe we should add an …

    chipx86chipx86

    Blank line between these.

    chipx86chipx86

    And here.

    chipx86chipx86

    Can we be sure that this will be true for every extension resource? I've written one or two toy extension …

    mike_conleymike_conley
    chipx86
    1. 
        
    2. djblets/extensions/models.py (Diff revision 1)
       
       
       
       
      Show all issues
      Managers, no, but unless an extension has its own ExtensionManager, there will only be one. (Maybe we should add an ID for the ExtensionManager and include that as a field for the extension's model).
      
      As for the extension, the extension ID is the class name (see line 436). So, you can just call get_installed_extension(self.class_name).
      1. I was wondering where the id was set, thanks :D
    3. djblets/extensions/resources.py (Diff revision 1)
       
       
       
      Show all issues
      Blank line between these.
    4. djblets/extensions/resources.py (Diff revision 1)
       
       
       
      Show all issues
      And here.
    5. 
        
    SM
    mike_conley
    1. Hey Steven,
      
      Just one question - see below,
      
      -Mike
    2. djblets/extensions/resources.py (Diff revision 2)
       
       
      Show all issues
      Can we be sure that this will be true for every extension resource?
      
      I've written one or two toy extension that use PUT and DELETE, and don't respond to GET...
      
      Or am I missing an assumption here?
      1. Thanks for pointing this out, I probably should have explained myself:
        
        I'm hard coding 'GET' here to be consistent with the regular resource tree.
        If you look at the `djblets.webapi.resources.WebAPIResource` class, in
        `get_links()` you will see:
        
            for resource in resources:
                links[resource.name_plural] = {
                    'method': 'GET',
                    'href': '%s%s/' % (clean_base_href, resource.uri_name),
                }
        
        `resources` is an argument (either list_child_resources, or
        item_child_resources). So any child resources are always linked like this,
        even when they don't have a 'GET' method.
        
        At first this seemed like a bug to me, but I figure it's probably done
        this way for a reason. the structure of the links in a resource go
        like this:
        
            "links": {
                "self": { "method": "GET", "href": ... },
                "create": { "method": "POST", "href": ...},
                ...
                "child_resource_name": { "method": "GET", "href": ... },
                ...
            }
        
        "self" always exists, and elements like "create" are there if the method
        is supported. For each child resource, you only get one entry with the
        resources name, and the method is always "GET", even if GET isn't
        supported. Since we can only have a single method, it probably makes sense
        to default it to "GET".
        
        The only other option I can think of is to set some sort of priority, such
        that the highest priority method supported is displayed. The problem with
        this is you can't decide which methods a resource supports without some
        extra knowledge not present in the tree.
        
        Taking all that into consideration, I'd say a good way to deal with
        resources is always have a "GET" method. This ensures the URL for
        the resource will always return something meaningful when traversing the
        tree, and you can discover exactly which methods are supported by looking
        at the resource's links. Even if your resource won't return anything
        meaningful, just use the default GET handler, and it will display the links
        and an empty set for the resources data.
        
        I hope this clears everything up, please let me know how you think I should
        proceed with this.
      2. I wonder what others out there do.
        
        I'm not a huge fan of hard-coding GET, but it may be a necessary evil right now. We *should* be able to detect whether the resource supports GET, though, by looking at allowed_methods.
        
        Perhaps we can check if GET is supported, and if not, change that link to be OPTIONS. No payload to fetch, but OPTIONS would give us the list of methods allowed.
      3. I'm going to drop this for now, and take a look at fixing it in general sometime down the road.
    3. 
        
    mike_conley
    1. Ship It!
    2. 
        
    chipx86
    1. Ship It!
    2. 
        
    SM
    Review request changed
    Status:
    Completed
    Change Summary:
    Pushed to master (dfa8116)