Skip to content
Browse files

Ruby 1.9: ERB template encoding using a magic comment at the top of t…

…he file
  • Loading branch information...
1 parent e23554d commit 5ec2c7dc29b36d85b2658465b8a979deb0529d7e @jeremy jeremy committed May 28, 2009
View
3 actionpack/CHANGELOG
@@ -1,5 +1,8 @@
*Edge*
+* Ruby 1.9: ERB template encoding using a magic comment at the top of the file. [Jeremy Kemper]
+ <%# encoding: utf-8 %>
+
* Change integration test helpers to accept Rack environment instead of just HTTP Headers [Pratik Naik]
Before : get '/path', {}, 'Accept' => 'text/javascript'
View
6 actionpack/lib/action_view/template/handlers/erb.rb
@@ -16,11 +16,7 @@ class ERB < TemplateHandler
self.default_format = Mime::HTML
def compile(template)
- src = ::ERB.new("<% __in_erb_template=true %>#{template.source}", nil, erb_trim_mode, '@output_buffer').src
-
- # Ruby 1.9 prepends an encoding to the source. However this is
- # useless because you can only set an encoding on the first line
- RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
+ ::ERB.new("<% __in_erb_template=true %>#{template.source}", nil, erb_trim_mode, '@output_buffer').src
end
end
end
View
16 actionpack/lib/action_view/template/template.rb
@@ -52,16 +52,26 @@ def compile(locals, view)
locals_code = locals.keys.map! { |key| "#{key} = local_assigns[:#{key}];" }.join
+ code = @handler.call(self)
+ encoding_comment = $1 if code.sub!(/\A(#.*coding.*)\n/, '')
+
source = <<-end_src
def #{method_name}(local_assigns)
- old_output_buffer = output_buffer;#{locals_code};#{@handler.call(self)}
+ old_output_buffer = output_buffer;#{locals_code};#{code}
ensure
self.output_buffer = old_output_buffer
end
end_src
+ if encoding_comment
+ source = "#{encoding_comment}\n#{source}"
+ line = -1
+ else
+ line = 0
+ end
+
begin
- ActionView::Base::CompiledTemplates.module_eval(source, identifier, 0)
+ ActionView::Base::CompiledTemplates.module_eval(source, identifier, line)
method_name
rescue Exception => e # errors from template code
if logger = (view && view.logger)
@@ -79,4 +89,4 @@ def build_method_name(locals)
"_render_template_#{@identifier.hash}_#{__id__}_#{locals.keys.hash}".gsub('-', "_")
end
end
-end
+end
View
5 actionpack/test/fixtures/test/utf8.html.erb
@@ -1,2 +1,5 @@
+<%# encoding: utf-8 -%>
Русский текст
-日本語のテキスト
+<%= "".encoding %>
+<%= @output_buffer.encoding %>
+<%= __ENCODING__ %>
View
2 actionpack/test/template/render_test.rb
@@ -249,7 +249,7 @@ def test_render_with_nested_layout
if '1.9'.respond_to?(:force_encoding)
def test_render_utf8_template
result = @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield")
- assert_equal "Русский текст\n日本語のテキスト", result
+ assert_equal "Русский текст\nUTF-8\nUTF-8\nUTF-8\n", result
assert_equal Encoding::UTF_8, result.encoding
end
end

3 comments on commit 5ec2c7d

@botanicus

Encoding.default_external = "utf-8" isn't enough?

@qoobaa
qoobaa commented on 5ec2c7d May 31, 2009

The magic comment in the template has completely no effect, you can put whatever you want there: <%# encoding: utf-64 %> also pass the test.

@jeremy
Ruby on Rails member
jeremy commented on 5ec2c7d Jun 1, 2009

The test was fooled by the default encoding. Fixed.

Please sign in to comment.
Something went wrong with that request. Please try again.