Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added proper getters and setters for content type and charset [DHH] A…
…dded utf-8 as the default charset for all renders. You can change this default using ActionController::Base.default_charset=(encoding) [DHH]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5129 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
dhh committed Sep 17, 2006
1 parent 55c6c64 commit 2caf4d5
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 14 deletions.
11 changes: 11 additions & 0 deletions actionpack/CHANGELOG
@@ -1,5 +1,16 @@
*SVN*

* Added utf-8 as the default charset for all renders. You can change this default using ActionController::Base.default_charset=(encoding) [DHH]

* Added proper getters and setters for content type and charset [DHH]. Example of what we used to do:

response.headers["Content-Type"] = "application/atom+xml; charset=utf-8"

...now:

response.content_type = Mime::ATOM
response.charset = "utf-8"

* Updated prototype.js to 1.5.0_rc1 with latest fixes. [Rick Olson]

- XPATH support
Expand Down
16 changes: 13 additions & 3 deletions actionpack/lib/action_controller/base.rb
Expand Up @@ -272,6 +272,10 @@ class Base
@@param_parsers = { Mime::XML => :xml_simple }
cattr_accessor :param_parsers

# Controls the default charset for all renders.
@@default_charset = "utf-8"
cattr_accessor :default_charset

# Template root determines the base from which template references will be made. So a call to render("test/template")
# will be converted to "#{template_root}/test/template.rhtml".
class_inheritable_accessor :template_root
Expand Down Expand Up @@ -420,6 +424,7 @@ def process(request, response, method = :perform_action, *arguments) #:nodoc:
log_processing
send(method, *arguments)

assign_default_content_type_and_charset
response
ensure
process_cleanup
Expand Down Expand Up @@ -703,7 +708,7 @@ def render(options = nil, deprecated_status = nil, &block) #:doc:
end

if content_type = options[:content_type]
headers["Content-Type"] = content_type.to_s
response.content_type = content_type.to_s
end

if text = options[:text]
Expand Down Expand Up @@ -793,12 +798,12 @@ def render_text(text = nil, status = nil) #:nodoc:
end

def render_javascript(javascript, status = nil) #:nodoc:
response.headers['Content-Type'] = 'text/javascript; charset=UTF-8'
response.content_type = Mime::JS
render_text(javascript, status)
end

def render_xml(xml, status = nil) #:nodoc:
response.headers['Content-Type'] = 'application/xml'
response.content_type = Mime::XML
render_text(xml, status)
end

Expand Down Expand Up @@ -1034,6 +1039,11 @@ def assign_names
@action_name = (params['action'] || 'index')
end

def assign_default_content_type_and_charset
response.content_type ||= Mime::HTML
response.charset ||= self.class.default_charset
end

def action_methods
self.class.action_methods
end
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/caching.rb
Expand Up @@ -210,7 +210,7 @@ def after(controller)
def set_content_type!(action_cache_path)
if extention = action_cache_path.extension
content_type = Mime::EXTENSION_LOOKUP[extention]
action_cache_path.controller.headers['Content-Type'] = content_type.to_s
action_cache_path.controller.content_type = content_type.to_s
end
end

Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/rescue.rb
Expand Up @@ -71,7 +71,7 @@ def rescue_action_locally(exception)

@template.instance_variable_set("@contents", @template.render_file(template_path_for_local_rescue(exception), false))

@headers["Content-Type"] = "text/html"
response.content_type = Mime::HTML
render_file(rescues_path("layout"), response_code_for_rescue(exception))
end

Expand Down
18 changes: 18 additions & 0 deletions actionpack/lib/action_controller/response.rb
Expand Up @@ -7,6 +7,24 @@ def initialize
@body, @headers, @session, @assigns = "", DEFAULT_HEADERS.merge("cookie" => []), [], []
end

def content_type=(mime_type)
@headers["Content-Type"] = charset ? "#{mime_type}; charset=#{charset}" : mime_type
end

def content_type
content_type = String(@headers["Content-Type"]).split(";")[0]
content_type.blank? ? nil : content_type
end

def charset=(encoding)
@headers["Content-Type"] = "#{content_type || "text/html"}; charset=#{encoding}"
end

def charset
charset = String(@headers["Content-Type"]).split(";")[1]
charset.blank? ? nil : charset.strip.split("=")[1]
end

def redirect(to_url, permanently = false)
@headers["Status"] = "302 Found" unless @headers["Status"] == "301 Moved Permanently"
@headers["location"] = to_url
Expand Down
7 changes: 3 additions & 4 deletions actionpack/lib/action_view/base.rb
@@ -1,7 +1,6 @@
require 'erb'

module ActionView #:nodoc:

class ActionViewError < StandardError #:nodoc:
end

Expand Down Expand Up @@ -441,11 +440,11 @@ def create_template_source(extension, template, render_symbol, locals)
if template_requires_setup?(extension)
body = case extension.to_sym
when :rxml
"@controller.response.content_type ||= 'application/xml'\n" +
"xml = Builder::XmlMarkup.new(:indent => 2)\n" +
"@controller.headers['Content-Type'] ||= 'application/xml'\n" +
template
when :rjs
"@controller.headers['Content-Type'] ||= 'text/javascript'\n" +
"@controller.response.content_type ||= 'text/javascript'\n" +
"update_page do |page|\n#{template}\nend"
end
else
Expand Down Expand Up @@ -526,4 +525,4 @@ def compile_template(extension, template, file_name, local_assigns)
end
end

require 'action_view/template_error'
require 'action_view/template_error'
6 changes: 3 additions & 3 deletions actionpack/test/controller/action_pack_assertions_test.rb
Expand Up @@ -568,18 +568,18 @@ def setup

def test_rendering_xml_sets_content_type
assert_deprecated(/render/) { process :hello_xml_world }
assert_equal('application/xml', @controller.headers['Content-Type'])
assert_equal('application/xml; charset=utf-8', @controller.headers['Content-Type'])
end

def test_rendering_xml_respects_content_type
@response.headers['Content-Type'] = 'application/pdf'
assert_deprecated(/render/) { process :hello_xml_world }
assert_equal('application/pdf', @controller.headers['Content-Type'])
assert_equal('application/pdf; charset=utf-8', @controller.headers['Content-Type'])
end


def test_render_text_with_custom_content_type
get :render_text_with_custom_content_type
assert_equal 'application/rss+xml', @response.headers['Content-Type']
assert_equal 'application/rss+xml; charset=utf-8', @response.headers['Content-Type']
end
end
99 changes: 99 additions & 0 deletions actionpack/test/controller/content_type_test.rb
@@ -0,0 +1,99 @@
require File.dirname(__FILE__) + '/../abstract_unit'

class ContentTypeController < ActionController::Base
def render_content_type_from_body
response.content_type = Mime::RSS
render :text => "hello world!"
end

def render_defaults
render :text => "hello world!"
end

def render_content_type_from_render
render :text => "hello world!", :content_type => Mime::RSS
end

def render_charset_from_body
response.charset = "utf-16"
render :text => "hello world!"
end

def render_default_for_rhtml
end

def render_default_for_rxml
end

def render_change_for_rxml
response.content_type = Mime::HTML
render :action => "render_default_for_rxml"
end

def rescue_action(e) raise end
end

ContentTypeController.template_root = File.dirname(__FILE__) + "/../fixtures/"

class ContentTypeTest < Test::Unit::TestCase
def setup
@controller = ContentTypeController.new

# enable a logger so that (e.g.) the benchmarking stuff runs, so we can get
# a more accurate simulation of what happens in "real life".
@controller.logger = Logger.new(nil)

@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
end

def test_render_defaults
get :render_defaults
assert_equal "utf-8", @response.charset
assert_equal Mime::HTML, @response.content_type
end

def test_render_changed_charset_default
ContentTypeController.default_charset = "utf-16"
get :render_defaults
assert_equal "utf-16", @response.charset
assert_equal Mime::HTML, @response.content_type
ContentTypeController.default_charset = "utf-8"
end

def test_content_type_from_body
get :render_content_type_from_body
assert_equal "application/rss+xml", @response.content_type
assert_equal "utf-8", @response.charset
end

def test_content_type_from_render
get :render_content_type_from_render
assert_equal "application/rss+xml", @response.content_type
assert_equal "utf-8", @response.charset
end

def test_charset_from_body
get :render_charset_from_body
assert_equal "utf-16", @response.charset
assert_equal Mime::HTML, @response.content_type
end

def test_default_for_rhtml
get :render_default_for_rhtml
assert_equal Mime::HTML, @response.content_type
assert_equal "utf-8", @response.charset
end

def test_default_for_rxml
get :render_default_for_rxml
assert_equal Mime::XML, @response.content_type
assert_equal "utf-8", @response.charset
end

def test_change_for_rxml
get :render_change_for_rxml
assert_equal Mime::HTML, @response.content_type
assert_equal "utf-8", @response.charset
end
end
9 changes: 7 additions & 2 deletions actionpack/test/controller/new_render_test.rb
Expand Up @@ -263,6 +263,11 @@ def yield_content_for
render :action => "content_for", :layout => "yield"
end

def render_content_type_from_body
response.content_type = Mime::RSS
render :text => "hello world!"
end

def rescue_action(e) raise end

private
Expand Down Expand Up @@ -572,14 +577,14 @@ def test_render_text_with_assigns
def test_update_page
get :update_page
assert_template nil
assert_equal 'text/javascript; charset=UTF-8', @response.headers['Content-Type']
assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type']
assert_equal 2, @response.body.split($/).length
end

def test_update_page_with_instance_variables
get :update_page_with_instance_variables
assert_template nil
assert_equal 'text/javascript; charset=UTF-8', @response.headers['Content-Type']
assert_equal 'text/javascript; charset=utf-8', @response.headers['Content-Type']
assert_match /balance/, @response.body
assert_match /\$37/, @response.body
end
Expand Down
@@ -0,0 +1 @@
<%= 'hello world!' %>
@@ -0,0 +1 @@
xml.p "Hello world!"

0 comments on commit 2caf4d5

Please sign in to comment.