Skip to content

Instantly share code, notes, and snippets.

@elomar
Created June 7, 2010 19:53
Show Gist options
  • Save elomar/429099 to your computer and use it in GitHub Desktop.
Save elomar/429099 to your computer and use it in GitHub Desktop.
Ideias on a nicer ActiveResource API
= ActiveResource
== Guidelines
ARes is a platform to build clients to restful-like web services. It maps resources to objects that complies with the ActiveModel API.
To enjoy the advantages of being restful (whose discussion is beyond the scope of this gist), ARes should support:
* using HTTP verbs, headers and status code as they are meant;
* using hypermedia to drive application state and navigate between resources;
* different and vendored media-types
* the dinamic creation of resource types
When consuming Rails powered services, ARes defaults should match Rails defaults and ARes should work out of the box - basic crud, validations, associations. ARes should also be able to consume non-rails servers easily.
== Example client code
person = ActiveResource::Resource.at("http://example.com/people/1")
<< ActiveResource::Resource not loaded yet
# will be loadded by getting to uri when trying to access some attribute or link
person.name
person.parent # given parent is a link
<< ActiveResource::Resource, not loaded yet
person.parent.name
<< automatically gets parent href
person.parent.as("application/vnd.parent+xml")
person.parent.update_attribute(:name, "Paul")
# issues PATCH (or PUT) request to parent uri
person.brothers << {name: "Malena"}
person.save
# issues POST to brothers url
ActiveResource::Resource.at("http://example.com/people/1").as(:xml) # uses built-in xml formatter
ActiveResource::Resource.at("http://example.com/people/1".as("application/vnd.sun.Status+json") # uses built-in json formatter
ActiveResource::Resource.at("http://example.com/people/1").as(MyMediaTypeFormatter)
ActiveResource.at("http://example.com/people/1").get / post / put / delete
ActiveResource.at("http://example.com/people/1").update_attribute / save / destroy
ActiveResource.at("http://example.com/people").first / all / last / new / create
ActiveResource.at("http://example.com").at("/people")
class Person < ActiveResource::Base
at "http://example.com"
as :xml
end
class Person < ActiveResource::Base
site "http://example.com"
media_type :xml
end
Person.all ...
@technoweenie
Copy link

Still thinking about link headers... I could just encode pagination info there.

Link: </users?limit=30&after=232232> railstag="next"; </users?limit=30&after232202> railstag="prev"

This is very loosely based on Riak link headers.

@josevalim
Copy link

About 1 to 5: agreed! URI templates sounds interesting. Definitely worth the investigation.

However, I didn't understand what you mean with: "Also, I hate how Rails adds the nested hash to every item." But yes, the issue could probably be solved by custom formatters/mime types.

@technoweenie
Copy link

Sorry, I'm only talking about JSON. It wraps every object in a hash so that you can access it like xml/form responses with something like params[:ticket].

$ curl http://rails.lighthouseapp.com/projects/8994/tickets.json | json_reformat
  "tickets": [
    {
      "ticket": { ... },
      "ticket": { ... }
    }

@josevalim
Copy link

:emo: this is indeed ugly. Maybe we could move this concern to the formatter and it would receive an array of hashes but would properly parse it and create params[:ticket] based on the root name.

@technoweenie
Copy link

Yes, based on a custom mime type. That rocks :) So much cleaner than param_parsers. That's exactly what I was thinking with that collected_as example above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment