aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2009-07-31 21:49:29 +0200
committerJosé Valim <jose.valim@gmail.com>2009-07-31 21:49:29 +0200
commit072c87b532a0bfb334787928248863a2561dc849 (patch)
tree1011ad044643449db9441874fa330d3486644749 /actionpack/lib/action_controller
parent62fd1d3716b4b5fd1d91cdcc77003efe80fc5a7e (diff)
parentb2d24baf790fee4f932fa32a8ae94f0212d14ad9 (diff)
downloadrails-072c87b532a0bfb334787928248863a2561dc849.tar.gz
rails-072c87b532a0bfb334787928248863a2561dc849.tar.bz2
rails-072c87b532a0bfb334787928248863a2561dc849.zip
Merge branch 'respond_with'
Diffstat (limited to 'actionpack/lib/action_controller')
-rw-r--r--actionpack/lib/action_controller/base/mime_responds.rb128
1 files changed, 81 insertions, 47 deletions
diff --git a/actionpack/lib/action_controller/base/mime_responds.rb b/actionpack/lib/action_controller/base/mime_responds.rb
index f4a4007a43..9a6c8aa58b 100644
--- a/actionpack/lib/action_controller/base/mime_responds.rb
+++ b/actionpack/lib/action_controller/base/mime_responds.rb
@@ -177,19 +177,21 @@ module ActionController #:nodoc:
# Be sure to check respond_with and respond_to documentation for more examples.
#
def respond_to(*mimes, &block)
- options = mimes.extract_options!
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
- resource = options.delete(:with)
responder = Responder.new
-
mimes = collect_mimes_from_class_level if mimes.empty?
mimes.each { |mime| responder.send(mime) }
block.call(responder) if block_given?
if format = request.negotiate_mime(responder.order)
- respond_to_block_or_template_or_resource(format, resource,
- options, &responder.response_for(format))
+ self.formats = [format.to_sym]
+
+ if response = responder.response_for(format)
+ response.call
+ else
+ default_render
+ end
else
head :not_acceptable
end
@@ -200,11 +202,11 @@ module ActionController #:nodoc:
# formats allowed:
#
# class PeopleController < ApplicationController
- # respond_to :html, :xml, :json
+ # respond_to :xml, :json
#
# def index
# @people = Person.find(:all)
- # respond_with(@person)
+ # respond_with(@people)
# end
# end
#
@@ -214,67 +216,99 @@ module ActionController #:nodoc:
#
# If neither are available, it will raise an error.
#
- # Extra parameters given to respond_with are used when :to_format is invoked.
- # This allows you to set status and location for several formats at the same
- # time. Consider this restful controller response on create for both xml
- # and json formats:
+ # respond_with holds semantics for each HTTP verb. The example above cover
+ # GET requests. Let's check a POST request example:
+ #
+ # def create
+ # @person = Person.new(params[:person])
+ # @person.save
+ # respond_with(@person)
+ # end
+ #
+ # Since the request is a POST, respond_with will check wether @people
+ # resource have errors or not. If it has errors, it will render the error
+ # object with unprocessable entity status (422).
+ #
+ # If no error was found, it will render the @people resource, with status
+ # created (201) and location header set to person_url(@people).
+ #
+ # If you also want to provide html behavior in the method above, you can
+ # supply a block to customize it:
#
# class PeopleController < ApplicationController
- # respond_to :xml, :json
+ # respond_to :html, :xml, :json # Add :html to respond_to definition
#
# def create
- # @person = Person.new(params[:person])
- #
- # if @person.save
- # respond_with(@person, :status => :ok, :location => person_url(@person))
- # else
- # respond_with(@person.errors, :status => :unprocessable_entity)
+ # @person = Person.new(params[:pe])
+ #
+ # respond_with(@person) do |format|
+ # if @person.save
+ # flash[:notice] = 'Person was successfully created.'
+ # format.html { redirect_to @person }
+ # else
+ # format.html { render :action => "new" }
+ # end
# end
# end
# end
#
- # Finally, respond_with also accepts blocks, as in respond_to. Let's take
- # the same controller and create action above and add common html behavior:
+ # It works similarly for PUT requests:
#
- # class PeopleController < ApplicationController
- # respond_to :html, :xml, :json
+ # def update
+ # @person = Person.find(params[:id])
+ # @person.update_attributes(params[:person])
+ # respond_with(@person)
+ # end
#
- # def create
- # @person = Person.new(params[:person])
+ # In case of failures, it works as POST requests, but in success failures
+ # it just reply status ok (200) to the client.
#
- # if @person.save
- # options = { :status => :ok, :location => person_url(@person) }
+ # A DELETE request also works in the same way:
#
- # respond_with(@person, options) do |format|
- # format.html { redirect_to options[:location] }
- # end
- # else
- # respond_with(@person.errors, :status => :unprocessable_entity) do
- # format.html { render :action => :new }
- # end
- # end
- # end
+ # def destroy
+ # @person = Person.find(params[:id])
+ # @person.destroy
+ # respond_with(@person)
# end
#
+ # It just replies with status ok, indicating the record was successfuly
+ # destroyed.
+ #
def respond_with(resource, options={}, &block)
- respond_to(options.merge!(:with => resource), &block)
+ respond_to(&block)
+ rescue ActionView::MissingTemplate => e
+ format = self.formats.first
+ resource = normalize_resource_options_by_verb(resource, options)
+
+ if resource.respond_to?(:"to_#{format}")
+ if options.delete(:no_content)
+ head options
+ else
+ render options.merge(format => resource)
+ end
+ else
+ raise e
+ end
end
protected
- def respond_to_block_or_template_or_resource(format, resource, options)
- self.formats = [format.to_sym]
- return yield if block_given?
+ # Change respond with behavior based on the HTTP verb.
+ #
+ def normalize_resource_options_by_verb(resource_or_array, options)
+ resource = resource_or_array.is_a?(Array) ? resource_or_array.last : resource_or_array
+ has_errors = resource.respond_to?(:errors) && !resource.errors.empty?
- begin
- default_render
- rescue ActionView::MissingTemplate => e
- if resource && resource.respond_to?(:"to_#{format.to_sym}")
- render options.merge(format.to_sym => resource)
- else
- raise e
- end
+ if has_errors && (request.post? || request.put?)
+ options.reverse_merge!(:status => :unprocessable_entity)
+ return resource.errors
+ elsif request.post?
+ options.reverse_merge!(:status => :created, :location => resource_or_array)
+ elsif !request.get?
+ options.reverse_merge!(:status => :ok, :no_content => true)
end
+
+ return resource
end
# Collect mimes declared in the class method respond_to valid for the