aboutsummaryrefslogtreecommitdiffstats
path: root/activeresource/README.rdoc
diff options
context:
space:
mode:
Diffstat (limited to 'activeresource/README.rdoc')
-rw-r--r--activeresource/README.rdoc165
1 files changed, 165 insertions, 0 deletions
diff --git a/activeresource/README.rdoc b/activeresource/README.rdoc
new file mode 100644
index 0000000000..127ac5b4a9
--- /dev/null
+++ b/activeresource/README.rdoc
@@ -0,0 +1,165 @@
+= Active Resource
+
+Active Resource (ARes) connects business objects and Representational State Transfer (REST)
+web services. It implements object-relational mapping for REST web services to provide transparent
+proxying capabilities between a client (ActiveResource) and a RESTful service (which is provided by Simply RESTful routing
+in ActionController::Resources).
+
+== Philosophy
+
+Active Resource attempts to provide a coherent wrapper object-relational mapping for REST
+web services. It follows the same philosophy as Active Record, in that one of its prime aims
+is to reduce the amount of code needed to map to these resources. This is made possible
+by relying on a number of code- and protocol-based conventions that make it easy for Active Resource
+to infer complex relations and structures. These conventions are outlined in detail in the documentation
+for ActiveResource::Base.
+
+== Overview
+
+Model classes are mapped to remote REST resources by Active Resource much the same way Active Record maps model classes to database
+tables. When a request is made to a remote resource, a REST XML request is generated, transmitted, and the result
+received and serialized into a usable Ruby object.
+
+=== Configuration and Usage
+
+Putting Active Resource to use is very similar to Active Record. It's as simple as creating a model class
+that inherits from ActiveResource::Base and providing a <tt>site</tt> class variable to it:
+
+ class Person < ActiveResource::Base
+ self.site = "http://api.people.com:3000/"
+ end
+
+Now the Person class is REST enabled and can invoke REST services very similarly to how Active Record invokes
+lifecycle methods that operate against a persistent store.
+
+ # Find a person with id = 1
+ ryan = Person.find(1)
+ Person.exists?(1) #=> true
+
+As you can see, the methods are quite similar to Active Record's methods for dealing with database
+records. But rather than dealing directly with a database record, you're dealing with HTTP resources (which may or may not be database records).
+
+==== Protocol
+
+Active Resource is built on a standard XML format for requesting and submitting resources over HTTP. It mirrors the RESTful routing
+built into Action Controller but will also work with any other REST service that properly implements the protocol.
+REST uses HTTP, but unlike "typical" web applications, it makes use of all the verbs available in the HTTP specification:
+
+* GET requests are used for finding and retrieving resources.
+* POST requests are used to create new resources.
+* PUT requests are used to update existing resources.
+* DELETE requests are used to delete resources.
+
+For more information on how this protocol works with Active Resource, see the ActiveResource::Base documentation;
+for more general information on REST web services, see the article here[http://en.wikipedia.org/wiki/Representational_State_Transfer].
+
+==== Find
+
+Find requests use the GET method and expect the XML form of whatever resource/resources is/are being requested. So,
+for a request for a single element, the XML of that item is expected in response:
+
+ # Expects a response of
+ #
+ # <person><id type="integer">1</id><attribute1>value1</attribute1><attribute2>..</attribute2></person>
+ #
+ # for GET http://api.people.com:3000/people/1.xml
+ #
+ ryan = Person.find(1)
+
+The XML document that is received is used to build a new object of type Person, with each
+XML element becoming an attribute on the object.
+
+ ryan.is_a? Person #=> true
+ ryan.attribute1 #=> 'value1'
+
+Any complex element (one that contains other elements) becomes its own object:
+
+ # With this response:
+ #
+ # <person><id>1</id><attribute1>value1</attribute1><complex><attribute2>value2</attribute2></complex></person>
+ #
+ # for GET http://api.people.com:3000/people/1.xml
+ #
+ ryan = Person.find(1)
+ ryan.complex #=> <Person::Complex::xxxxx>
+ ryan.complex.attribute2 #=> 'value2'
+
+Collections can also be requested in a similar fashion
+
+ # Expects a response of
+ #
+ # <people type="array">
+ # <person><id type="integer">1</id><first>Ryan</first></person>
+ # <person><id type="integer">2</id><first>Jim</first></person>
+ # </people>
+ #
+ # for GET http://api.people.com:3000/people.xml
+ #
+ people = Person.find(:all)
+ people.first #=> <Person::xxx 'first' => 'Ryan' ...>
+ people.last #=> <Person::xxx 'first' => 'Jim' ...>
+
+==== Create
+
+Creating a new resource submits the XML form of the resource as the body of the request and expects
+a 'Location' header in the response with the RESTful URL location of the newly created resource. The
+id of the newly created resource is parsed out of the Location response header and automatically set
+as the id of the ARes object.
+
+ # <person><first>Ryan</first></person>
+ #
+ # is submitted as the body on
+ #
+ # POST http://api.people.com:3000/people.xml
+ #
+ # when save is called on a new Person object. An empty response is
+ # is expected with a 'Location' header value:
+ #
+ # Response (201): Location: http://api.people.com:3000/people/2
+ #
+ ryan = Person.new(:first => 'Ryan')
+ ryan.new? #=> true
+ ryan.save #=> true
+ ryan.new? #=> false
+ ryan.id #=> 2
+
+==== Update
+
+'save' is also used to update an existing resource - and follows the same protocol as creating a resource
+with the exception that no response headers are needed - just an empty response when the update on the
+server side was successful.
+
+ # <person><first>Ryan</first></person>
+ #
+ # is submitted as the body on
+ #
+ # PUT http://api.people.com:3000/people/1.xml
+ #
+ # when save is called on an existing Person object. An empty response is
+ # is expected with code (204)
+ #
+ ryan = Person.find(1)
+ ryan.first #=> 'Ryan'
+ ryan.first = 'Rizzle'
+ ryan.save #=> true
+
+==== Delete
+
+Destruction of a resource can be invoked as a class and instance method of the resource.
+
+ # A request is made to
+ #
+ # DELETE http://api.people.com:3000/people/1.xml
+ #
+ # for both of these forms. An empty response with
+ # is expected with response code (200)
+ #
+ ryan = Person.find(1)
+ ryan.destroy #=> true
+ ryan.exists? #=> false
+ Person.delete(2) #=> true
+ Person.exists?(2) #=> false
+
+
+You can find more usage information in the ActiveResource::Base documentation.
+