123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- = 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.
- == Download and installation
- The latest version of Active Resource can be installed with RubyGems:
- % [sudo] gem install activeresource
- Source code can be downloaded as part of the Rails project on GitHub
- * https://github.com/rails/rails/tree/3-2-stable/activeresource
- === 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
- life cycle 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.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
- == License
- Active Resource is released under the MIT license.
- == Support
- API documentation is at
- * http://api.rubyonrails.org
- Bug reports and feature requests can be filed with the rest for the Ruby on Rails project here:
- * https://github.com/rails/rails/issues
- You can find more usage information in the ActiveResource::Base documentation.
|