Calling REST "<resource name>" creates a controller with the appropriate routes and maps your REST methods to standard Camping controller mehods. This is meant to be used in your Controllers module in place of R <routes>.
Your REST class should define the following methods:
create
read(id)
update(id)
destroy(id)
list
Routes will be automatically created based on the resource name fed to the REST method. Your class must have the same (but CamelCaps'ed) name as the resource name. So if your resource name is 'kittens', your controller class must be Kittens.
For example:
module Foobar::Controllers class Kittens < REST 'kittens' # POST /kittens def create end # GET /kittens/(\d+) def read(id) end # PUT /kittens/(\d+) def update(id) end # DELETE /kittens/(\d+) def destroy(id) end # GET /kittens def list end end end
Custom actions are also possible. For example, to implement a 'meow' action simply add a 'meow' method to the above controller:
# POST/GET/PUT/DELETE /kittens/meow # POST/GET/PUT/DELETE /kittens/(\d+)/meow def meow(id) end
Note that a custom action will respond to all four HTTP methods (POST/GET/PUT/DELETE).
Optionally, you can specify a :prefix key that will prepend the given string to the routes. For example, the following will create all of the above routes, prefixed with "/pets" (i.e. POST '/pets/kittens', GET '/pets/kittens/(\d+)', etc.):
module Foobar::Controllers class Items < REST 'kittens', :prefix => '/pets' # ... end end
Format-based routing similar to that in ActiveResource is also implemented. For example, to get a list of kittens in XML format, place a GET call to /kittens.xml. See the documentation for the render() method for more info.
# File lib/reststop.rb, line 300 def REST(r, options = {}) crud = R "#{options[:prefix]}/#{r}/([0-9a-zA-Z]+)/([a-z_]+)(?:\.[a-z]+)?", "#{options[:prefix]}/#{r}/([0-9a-zA-Z]+)(?:\.[a-z]+)?", "#{options[:prefix]}/#{r}/([a-z_]+)(?:\.[a-z]+)?", "#{options[:prefix]}/#{r}(?:\.[a-z]+)?" crud.module_eval do meta_def(:restful?){true} $LOG.debug("Creating RESTful controller for #{r.inspect} using Reststop #{::Reststop::VERSION::STRING}") if $LOG def get(id_or_custom_action = nil, custom_action = nil) # :nodoc: id = @input[:id] if @input[:id] custom_action = @input[:action] if @input[:action] if self.methods.include? id_or_custom_action custom_action ||= id_or_custom_action id ||= nil else id ||= id_or_custom_action end id = id.to_i if id && id =~ /^[0-9]+$/ @format = Controllers.read_format(@input, @env) begin if id.nil? && @input[:id].nil? custom_action ? send(custom_action) : list else custom_action ? send(custom_action, id || @input[:id]) : read(id || @input[:id]) end rescue NoMethodError => e # FIXME: this is probably not a good way to do this, but we need to somehow differentiate # between 'no such route' vs. other NoMethodErrors if e.message =~ /no such method/ return no_method(e) else raise e end rescue ActiveRecord::RecordNotFound => e return not_found(e) end end def post(custom_action = nil) # :nodoc: @format = Controllers.read_format(@input, @env) custom_action ? send(custom_action) : create end def put(id, custom_action = nil) # :nodoc: id = id.to_i if id =~ /^[0-9]+$/ @format = Controllers.read_format(@input, @env) custom_action ? send(custom_action, id || @input[:id]) : update(id || @input[:id]) end def delete(id, custom_action = nil) # :nodoc: id = id.to_i if id =~ /^[0-9]+$/ @format = Controllers.read_format(@input, @env) custom_action ? send(custom_action, id || @input[:id]) : destroy(id || @input[:id]) end private def _error(message, status_code = 500, e = nil) @status = status_code @message = message begin render "error_#{status_code}".intern rescue NoMethodError if @format.to_s == 'XML' "<error code='#{status_code}'>#{@message}</error>" else out = "<strong>#{@message}</strong>" out += "<pre style='color: #bbb'><strong>#{e.class}: #{e}</strong>\n#{e.backtrace.join("\n")}</pre>" if e out end end end def no_method(e) _error("No controller method responds to this route!", 501, e) end def not_found(e) _error("Record not found!", 404, e) end end crud end
# File lib/reststop.rb, line 367 def _error(message, status_code = 500, e = nil) @status = status_code @message = message begin render "error_#{status_code}".intern rescue NoMethodError if @format.to_s == 'XML' "<error code='#{status_code}'>#{@message}</error>" else out = "<strong>#{@message}</strong>" out += "<pre style='color: #bbb'><strong>#{e.class}: #{e}</strong>\n#{e.backtrace.join("\n")}</pre>" if e out end end end
Generated with the Darkfish Rdoc Generator 2.