1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Added responds_to to new base.

This commit is contained in:
Yehuda Katz + Carl Lerche 2009-05-20 15:33:08 -07:00
parent c03b0ca7eb
commit 01f032f256
11 changed files with 148 additions and 125 deletions

View file

@ -66,7 +66,12 @@ module AbstractController
raise ArgumentError, "String, false, or nil expected; you passed #{name.inspect}"
end
name && view_paths.find_by_parts(name, {:formats => formats}, "layouts")
name && view_paths.find_by_parts(name, {:formats => formats}, _layout_prefix(name))
end
# TODO: Decide if this is the best hook point for the feature
def _layout_prefix(name)
"layouts"
end
def _default_layout(require_layout = false)

View file

@ -1,111 +1,103 @@
module ActionController #:nodoc:
module MimeResponds #:nodoc:
def self.included(base)
base.module_eval do
include ActionController::MimeResponds::InstanceMethods
end
end
module InstanceMethods
# Without web-service support, an action which collects the data for displaying a list of people
# might look something like this:
#
# def index
# @people = Person.find(:all)
# end
#
# Here's the same action, with web-service support baked in:
#
# def index
# @people = Person.find(:all)
#
# respond_to do |format|
# format.html
# format.xml { render :xml => @people.to_xml }
# end
# end
#
# What that says is, "if the client wants HTML in response to this action, just respond as we
# would have before, but if the client wants XML, return them the list of people in XML format."
# (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
#
# Supposing you have an action that adds a new person, optionally creating their company
# (by name) if it does not already exist, without web-services, it might look like this:
#
# def create
# @company = Company.find_or_create_by_name(params[:company][:name])
# @person = @company.people.create(params[:person])
#
# redirect_to(person_list_url)
# end
#
# Here's the same action, with web-service support baked in:
#
# def create
# company = params[:person].delete(:company)
# @company = Company.find_or_create_by_name(company[:name])
# @person = @company.people.create(params[:person])
#
# respond_to do |format|
# format.html { redirect_to(person_list_url) }
# format.js
# format.xml { render :xml => @person.to_xml(:include => @company) }
# end
# end
#
# If the client wants HTML, we just redirect them back to the person list. If they want Javascript
# (format.js), then it is an RJS request and we render the RJS template associated with this action.
# Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
# include the person's company in the rendered XML, so you get something like this:
#
# <person>
# <id>...</id>
# ...
# <company>
# <id>...</id>
# <name>...</name>
# ...
# </company>
# </person>
#
# Note, however, the extra bit at the top of that action:
#
# company = params[:person].delete(:company)
# @company = Company.find_or_create_by_name(company[:name])
#
# This is because the incoming XML document (if a web-service request is in process) can only contain a
# single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
#
# person[name]=...&person[company][name]=...&...
#
# And, like this (xml-encoded):
#
# <person>
# <name>...</name>
# <company>
# <name>...</name>
# </company>
# </person>
#
# In other words, we make the request so that it operates on a single entity's person. Then, in the action,
# we extract the company data from the request, find or create the company, and then create the new person
# with the remaining data.
#
# Note that you can define your own XML parameter parser which would allow you to describe multiple entities
# in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
# and accept Rails' defaults, life will be much easier.
#
# If you need to use a MIME type which isn't supported by default, you can register your own handlers in
# environment.rb as follows.
#
# Mime::Type.register "image/jpg", :jpg
def respond_to(*types, &block)
raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
block ||= lambda { |responder| types.each { |type| responder.send(type) } }
responder = Responder.new(self)
block.call(responder)
responder.respond
end
# Without web-service support, an action which collects the data for displaying a list of people
# might look something like this:
#
# def index
# @people = Person.find(:all)
# end
#
# Here's the same action, with web-service support baked in:
#
# def index
# @people = Person.find(:all)
#
# respond_to do |format|
# format.html
# format.xml { render :xml => @people.to_xml }
# end
# end
#
# What that says is, "if the client wants HTML in response to this action, just respond as we
# would have before, but if the client wants XML, return them the list of people in XML format."
# (Rails determines the desired response format from the HTTP Accept header submitted by the client.)
#
# Supposing you have an action that adds a new person, optionally creating their company
# (by name) if it does not already exist, without web-services, it might look like this:
#
# def create
# @company = Company.find_or_create_by_name(params[:company][:name])
# @person = @company.people.create(params[:person])
#
# redirect_to(person_list_url)
# end
#
# Here's the same action, with web-service support baked in:
#
# def create
# company = params[:person].delete(:company)
# @company = Company.find_or_create_by_name(company[:name])
# @person = @company.people.create(params[:person])
#
# respond_to do |format|
# format.html { redirect_to(person_list_url) }
# format.js
# format.xml { render :xml => @person.to_xml(:include => @company) }
# end
# end
#
# If the client wants HTML, we just redirect them back to the person list. If they want Javascript
# (format.js), then it is an RJS request and we render the RJS template associated with this action.
# Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also
# include the person's company in the rendered XML, so you get something like this:
#
# <person>
# <id>...</id>
# ...
# <company>
# <id>...</id>
# <name>...</name>
# ...
# </company>
# </person>
#
# Note, however, the extra bit at the top of that action:
#
# company = params[:person].delete(:company)
# @company = Company.find_or_create_by_name(company[:name])
#
# This is because the incoming XML document (if a web-service request is in process) can only contain a
# single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
#
# person[name]=...&person[company][name]=...&...
#
# And, like this (xml-encoded):
#
# <person>
# <name>...</name>
# <company>
# <name>...</name>
# </company>
# </person>
#
# In other words, we make the request so that it operates on a single entity's person. Then, in the action,
# we extract the company data from the request, find or create the company, and then create the new person
# with the remaining data.
#
# Note that you can define your own XML parameter parser which would allow you to describe multiple entities
# in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow
# and accept Rails' defaults, life will be much easier.
#
# If you need to use a MIME type which isn't supported by default, you can register your own handlers in
# environment.rb as follows.
#
# Mime::Type.register "image/jpg", :jpg
def respond_to(*types, &block)
raise ArgumentError, "respond_to takes either types or a block, never both" unless types.any? ^ block
block ||= lambda { |responder| types.each { |type| responder.send(type) } }
responder = Responder.new(self)
block.call(responder)
responder.respond
end
class Responder #:nodoc:
@ -127,8 +119,15 @@ module ActionController #:nodoc:
@order << mime_type
@responses[mime_type] ||= Proc.new do
@controller.template.formats = [mime_type.to_sym]
@response.content_type = mime_type.to_s
# TODO: Remove this when new base is merged in
if defined?(Http)
@controller.formats = [mime_type.to_sym]
@controller.template.formats = [mime_type.to_sym]
else
@controller.template.formats = [mime_type.to_sym]
@response.content_type = mime_type.to_s
end
block_given? ? block.call : @controller.send(:render, :action => @controller.action_name)
end
end

View file

@ -15,6 +15,7 @@ module ActionController
# require 'action_controller/routing'
autoload :Caching, 'action_controller/caching'
autoload :Dispatcher, 'action_controller/dispatch/dispatcher'
autoload :MimeResponds, 'action_controller/base/mime_responds'
autoload :PolymorphicRoutes, 'action_controller/routing/generation/polymorphic_routes'
autoload :RecordIdentifier, 'action_controller/record_identifier'
autoload :Resources, 'action_controller/routing/resources'

View file

@ -18,6 +18,7 @@ module ActionController
include SessionManagement
include ActionDispatch::StatusCodes
include ActionController::Caching
include ActionController::MimeResponds
# Rails 2.x compatibility
include ActionController::Rails2Compatibility

View file

@ -59,6 +59,11 @@ module ActionController
def initialize_template_class(*) end
def assign_shortcuts(*) end
# TODO: Remove this after we flip
def template
_action_view
end
module ClassMethods
def protect_from_forgery() end
def consider_all_requests_local() end
@ -95,10 +100,8 @@ module ActionController
super || (respond_to?(:method_missing) && "_handle_method_missing")
end
def _layout_for_name(name)
name &&= name.sub(%r{^/?layouts/}, '')
super
def _layout_prefix(name)
super unless name =~ /\blayouts/
end
end
end

View file

@ -18,7 +18,7 @@ module ActionController
_process_options(options)
if options.key?(:text)
options[:_template] = ActionView::TextTemplate.new(_text(options))
options[:_template] = ActionView::TextTemplate.new(_text(options), formats.first)
template = nil
elsif options.key?(:inline)
handler = ActionView::Template.handler_class_for_extension(options[:type] || "erb")

View file

@ -7,7 +7,7 @@ module ActionController
@_response = response
@_response.request = request
ret = process(request.parameters[:action])
@_response.body = self.response_body || " "
@_response.body ||= self.response_body || " "
@_response.prepare!
set_test_assigns
ret

View file

@ -41,6 +41,7 @@ module ActionController #:nodoc:
end
def recycle!
@formats = nil
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
@env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
@env['action_dispatch.request.query_parameters'] = {}

View file

@ -1,11 +1,16 @@
module ActionView #:nodoc:
class TextTemplate < String #:nodoc:
def initialize(string, content_type = Mime[:html])
super(string)
@content_type = Mime[content_type]
end
def identifier() self end
def render(*) self end
def mime_type() Mime::HTML end
def mime_type() @content_type end
def partial?() false end
end

View file

@ -48,6 +48,8 @@ class PageCachingTest < ActionController::TestCase
super
ActionController::Base.perform_caching = true
ActionController::Routing::Routes.clear!
ActionController::Routing::Routes.draw do |map|
map.main '', :controller => 'posts'
map.formatted_posts 'posts.:format', :controller => 'posts'

View file

@ -437,7 +437,7 @@ class MimeControllerTest < ActionController::TestCase
@controller.instance_eval do
def render(*args)
unless args.empty?
@action = args.first[:action]
@action = args.first[:action] || action_name
end
response.body = "#{@action} - #{@template.formats}"
end
@ -490,14 +490,15 @@ class PostController < AbstractPostController
end
end
protected
def with_iphone
Mime::Type.register_alias("text/html", :iphone)
request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone"
yield
ensure
Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) }
end
protected
def with_iphone
Mime::Type.register_alias("text/html", :iphone)
request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone"
yield
ensure
Mime.module_eval { remove_const :IPHONE if const_defined?(:IPHONE) }
end
end
class SuperPostController < PostController
@ -509,6 +510,11 @@ class SuperPostController < PostController
end
end
if ENV["new_base"]
PostController._write_layout_method
SuperPostController._write_layout_method
end
class MimeControllerLayoutsTest < ActionController::TestCase
tests PostController