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

truly nested resources #22

Open
apmorton opened this issue Jul 29, 2012 · 3 comments
Open

truly nested resources #22

apmorton opened this issue Jul 29, 2012 · 3 comments
Assignees
Milestone

Comments

@apmorton
Copy link

the github api makes use of nested resources, in this fashion

/repos/<username>/<repo>/hooks/<id>

in slumber (another api library) it looks like this

full_repo_name = 'user/repo'
api.repos(full_repo_name).hooks(id).get()

i dont think there is a nice way to do this with drest resources right now, you have to make open calls to the api.
some sort of interface like this would be very nice.

@derks
Copy link
Member

derks commented Jul 31, 2012

I'll need to spend some time working with the github api.. and see if I can figure out a proper interface for drest. I have some ideas, but it will take some time to iron out. I'm thinking of adding the ability to 'add_nested_resource()' similar to API.add_resource(). Like:

api = drest.api.API('http://localhost/api/v1/')
api.add_resource('repos', resource_handler=RepoResource)

# get repo
response = api.repos.get('john.doe', 'johns_repo')

# add nested resource
api.repos.add_nested_resource('hooks', resource_handler=HookResource)

# get hook id 12
response = api.repos.get('john.doe', 'johns_repo').hooks.get(12)

# or maybe
response = api.repos.hooks.get('john.doe', 'johns_repo', 12)

Other than adding the 'add_nested_resource()' for resources, It is possible to override the default resource handler to accomplish this now:

from drest.api import API
from drest.resource import RESTResourceHandler

class MyResource(RESTResourceHandler):
    def get(self, ...):
        # do whatever you want to get data
        return response

api = API('http://localhost/api/v1')
api.add_resource('repo_hooks', resource_handler=MyResource)
api.repo_hooks.get('john.doe', 'johns_repo', 12)

You just need to build the 'get()' args the way you want in order to build the 'path' for make_request. See: https://github.com/derks/drest/blob/master/drest/resource.py#L91

I'll try and build an example later on. Thanks for the feedback!

@ghost ghost assigned derks Jul 31, 2012
@apmorton
Copy link
Author

apmorton commented Aug 1, 2012

this is sorta unrelated, but I will put it here instead of opening a new issue.

one of the things I really liked about slumber was the way its 'resources' worked as opposed to drest. I would like to see some of the flexibility from slumbers interfaces brought to drest if possible, since it would increase the usability I think.

for some elaboration, I'm just going to show some code in slumber and drest i guess.

# assuming 'api' is our already setup API object

# slumber
api.users(1).get()
# GET /users/1/

# drest
api.users.get(1)
# GET /users/1/

one of the key differences is that in slumber, a resource is instantiated with its url parameters, instead of passing them to each request function. which allows you to do things like the following abit cleaner.

# slumber
myuser = api.users(1)
userdata = myuser.get()
userdata['name'] = 'john'
myuser.post(userdata)

# drest
userdata = api.users.get(1)
userdata['name'] = 'john'
api.users.post(1, userdata)

in that simple example its not a huge deal, but having to always pass around the data to be worked on AND the key required to again submit that data to the api can become hairy. of course you can simply use the key value from the retrieved data, but that also requires knowing what the name of that key is within the data, and no doubt becomes api specific. being able to pass around an instantiated resource object that points specifically to the resource you are working on is very nice.

some of the idioms in slumber make more sense to me, but unfortunately slumber is also lacking in some areas, and is not very flexible about its implementations.

one of the things in drest that makes little sense to me is having to register resources. I do see the flexibility it provides, being able to finely tune the ResourceHandler etc, but it should also be possible to implicitly create resources with all the assumed defaults of the API object by simply USING them.

api = drest.API(...)
api.myresource(1).get()
# GET /myresource/1/

just some ideas ive come across with my last project using drest/slumber, let me know what you think.

@derks
Copy link
Member

derks commented Aug 1, 2012

These are good ideas, and I really do appreciate the feedback. I had a similar thought to this a while back:

derks#1

The logistics are a bit out of date regarding current drest flow... but the idea is there. Perhaps making a 'ModelResource' that functions this way, or the way you are suggesting. More or less returning a ResourceResponseObject rather than a ResponseHandler.

user = api.users.get(1)
user['first_name'] = 'John'
user.save()  

Or:

user.put()

Conversly:

user = api.users.new()
user['first_name'] = 'Jane'
user.save()

OR

user.post()

I like the idea of simplifying it like a Model, rather than 'post()', 'put()', etc. Just:

# refresh data
user.get()

# post (if new) or put (if existing)
user.save()

# delete
user.delete()

With regard to your last point, the drest.api.TastyPieAPI() does auto-discover resources, because that is a known/common api interface that I can code around. I can do a get() on the base url, and get back a list of resource endpoints to create resources for. This is less reliable elsewhere.

http://drest.readthedocs.org/en/latest/api.html#drest.api.TastyPieAPI

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

2 participants