IMPORTANT: THIS IS A BACKPORT FOR RAILS 1.1.4. IF YOU ARE LOOKING FOR THE EDGE RAILS PLUGIN, YOU HAVE GONE ASTRAY! PLEASE READ BOTH README SECTIONS, 'ORIGINAL README' and 'BACKPORT README'. === ORIGINAL README === SimplyRestful ============= SimplyRestful is a plugin for implementing verb-oriented controllers. This is useful for implementing REST API's, where a single resource has different behavior based on the verb (method) used to access it. Giving credit where credit is due, this idea was inspired by reading: http://pezra.barelyenough.org/blog/2006/03/another-rest-controller-for-rails/ Because browsers don't yet support any verbs except GET and POST, you can send a parameter named "_method" and the plugin will use that as the request method, instead. For example: class MessagesController < ActionController::Base def index # return all messages end def new # return an HTML form for describing a new message end def create # create a new message end def show # find and return a specific message end def edit # return an HTML form for editing a specific message end def update # find and update a specific message end def destroy # delete a specific message end end Your routes would be something like: map.resource :message Then (using Net::HTTP to demonstrate the different verbs): Net::HTTP.start("localhost", 3000) do |http| # retrieve all messages response = http.get("/messages") # return an HTML form for defining a new message response = http.get("/messages/new") # create a new message response = http.post("/messages", "...") # retrieve message #1 response = http.get("/messages/1") # return an HTML form for editing an existing message response = http.get("/messages/1;edit") # update an existing message response = http.put("/messages/1", "...") # delete an existing message response = http.delete("/messages/1") end The #resource method accepts various options, too, to customize the resulting routes: map.resource :message, :path_prefix => "/thread/:thread_id" # --> GET /thread/7/messages/1 map.resource :message, :collection => { :rss => :get } # --> GET /messages;rss (maps to the #rss action) # also adds a url named "rss_messages" map.resource :message, :member => { :mark => :post } # --> POST /messages/1;mark (maps to the #mark action) # also adds a url named "mark_message" map.resource :message, :new => { :preview => :post } # --> POST /messages/new;preview (maps to the #preview action) # also adds a url named "preview_new_message" map.resource :message, :new => { :new => :any, :preview => :post } # --> POST /messages/new;preview (maps to the #preview action) # also adds a url named "preview_new_message" # --> /messages/new can be invoked via any request method map.resource :message, :controller => "categories", :path_prefix => "/category/:category_id", :name_prefix => "category_" # --> GET /categories/7/messages/1 # has named route "category_message" === BACKPORT README ==== USAGE FOR RAILS 1.1.4 README Following the DHH Keynote speech at RailsConf 2006, 'World of Resources', I wanted to play with REST in Rails, but only Edge Rails has the necessary features to use the SimplyRestful plugin that DHH mentioned in his speech. So, I took it upon myself to create a backport. It isn't the perfect solution -- waiting for 1.2 is the perfect solution. But for those of you who want that extra development time without sacrificing stability, this I think is a good compromise. If you want SimplyRestfulBackport to work, be aware of the following caveats: 1. The request_routing plugin is required. It is used for the :method requirement. 2. The tests should work on your system. Run them before using this backport. You will notice that I have included a modified version of assert_recognizes() in the test_helper. This appalling hack is to make the tests work with :method. 3. Rails 1.1.4 does not support route rule separators like ';', '.' and others. So, we have no '.:format' support. We will just have to wait for that one. Consequently, actions are treated as you would expect from 1.1.4 (examples modified from above): map.resource :message, :path_prefix => "/thread/:thread_id" # --> GET /thread/7/messages/1 map.resource :message, :collection => { :rss => :get } # --> GET /messages/rss (maps to the #rss action) # also adds a url named "rss_messages" map.resource :message, :member => { :mark => :post } # --> POST /messages/1/mark (maps to the #mark action) # also adds a url named "mark_message" map.resource :message, :new => { :preview => :post } # --> POST /messages/new/preview (maps to the #preview action) # also adds a url named "preview_new_message" map.resource :message, :new => { :new => :any, :preview => :post } # --> POST /messages/new/preview (maps to the #preview action) # also adds a url named "preview_new_message" # --> /messages/new can be invoked via any request method map.resource :message, :controller => "categories", :path_prefix => "/category/:category_id", :name_prefix => "category_" # --> GET /categories/7/messages/1 # has named route "category_message" BACKPORT BY MABS29