Changeset 8805
- Timestamp:
- 02/06/08 04:26:40 (3 months ago)
- Files:
-
- trunk/actionpack/CHANGELOG (modified) (1 diff)
- trunk/actionpack/lib/action_controller/base.rb (modified) (2 diffs)
- trunk/actionpack/lib/action_view.rb (modified) (1 diff)
- trunk/actionpack/lib/action_view/base.rb (modified) (6 diffs)
- trunk/actionpack/lib/action_view/template_error.rb (modified) (1 diff)
- trunk/actionpack/lib/action_view/template_handler.rb (modified) (1 diff)
- trunk/actionpack/lib/action_view/template_handlers/compilable.rb (modified) (5 diffs)
- trunk/actionpack/lib/action_view/template.rb (added)
- trunk/actionpack/test/controller/custom_handler_test.rb (modified) (3 diffs)
- trunk/actionpack/test/controller/render_test.rb (modified) (2 diffs)
- trunk/actionpack/test/template/compiled_templates_test.rb (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/actionpack/CHANGELOG
r8786 r8805 1 1 *SVN* 2 3 * Introduce a Template class to ActionView. #11024 [lifofifo] 2 4 3 5 * Introduce the :index option for form_for and fields_for to simplify multi-model forms (see http://railscasts.com/episodes/75). #9883 [rmm5t] trunk/actionpack/lib/action_controller/base.rb
r8683 r8805 6 6 require 'action_controller/url_rewriter' 7 7 require 'action_controller/status_codes' 8 require 'action_view/template' 8 9 require 'action_view/template_finder' 9 10 require 'drb' … … 867 868 elsif inline = options[:inline] 868 869 add_variables_to_assigns 869 render_for_text(@template.render_template(options[:type], inline, nil, options[:locals] || {}), options[:status]) 870 tmpl = ActionView::Template.new(@template, options[:inline], false, options[:locals], true, options[:type]) 871 render_for_text(@template.render_template(tmpl), options[:status]) 870 872 871 873 elsif action_name = options[:action] trunk/actionpack/lib/action_view.rb
r8689 r8805 29 29 30 30 require 'action_view/template_finder' 31 require 'action_view/template' 31 32 32 33 require 'action_view/base' trunk/actionpack/lib/action_view/base.rb
r8791 r8805 151 151 include ERB::Util 152 152 153 attr_reader :fi rst_render, :finder154 attr_accessor :base_path, :assigns, :template_extension 153 attr_reader :finder 154 attr_accessor :base_path, :assigns, :template_extension, :first_render 155 155 attr_accessor :controller 156 156 … … 174 174 @@cache_template_extensions = true 175 175 cattr_accessor :cache_template_extensions 176 177 # Specify whether local_assigns should be able to use string keys.178 # Defaults to +true+. String keys are deprecated and will be removed179 # shortly.180 @@local_assigns_support_string_keys = true181 cattr_accessor :local_assigns_support_string_keys182 176 183 177 # Specify whether RJS responses should be wrapped in a try/catch block … … 283 277 end 284 278 285 # Clear the forward slash at the beginning if exists 286 template_path = template_path.sub(/^\//, '') if use_full_path 287 288 @first_render ||= template_path 289 template_path_without_extension, template_extension = @finder.path_and_extension(template_path) 290 if use_full_path 291 if template_extension 292 template_file_name = @finder.pick_template(template_path_without_extension, template_extension) 293 else 294 template_extension = @finder.pick_template_extension(template_path).to_s 295 unless template_extension 296 raise ActionViewError, "No template found for #{template_path} in #{@finder.view_paths.inspect}" 297 end 298 template_file_name = @finder.pick_template(template_path, template_extension) 299 template_extension = template_extension.gsub(/^.+\./, '') # strip off any formats 300 end 301 else 302 template_file_name = template_path 303 end 304 305 template_source = nil # Don't read the source until we know that it is required 306 307 if template_file_name.blank? 308 raise ActionViewError, "Couldn't find template file for #{template_path} in #{@finder.view_paths.inspect}" 309 end 279 template = Template.new(self, template_path, use_full_path, local_assigns) 310 280 311 281 begin 312 render_template(template _extension, template_source, template_file_name, local_assigns)282 render_template(template) 313 283 rescue Exception => e 314 284 if TemplateError === e 315 e.sub_template_of(template _file_name)285 e.sub_template_of(template.filename) 316 286 raise e 317 287 else 318 raise TemplateError.new(@finder.find_base_path_for("#{template_path_without_extension}.#{template_extension}") || 319 @finder.view_paths.first, template_file_name, @assigns, template_source, e) 288 raise TemplateError.new(template, @assigns, e) 320 289 end 321 290 end … … 351 320 render_partial(options[:partial], ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]) 352 321 elsif options[:inline] 353 render_template(options[:type], options[:inline], nil, options[:locals]) 322 template = Template.new(self, options[:inline], false, options[:locals], true, options[:type]) 323 render_template(template) 354 324 end 355 325 end … … 358 328 # Renders the +template+ which is given as a string as either erb or builder depending on <tt>template_extension</tt>. 359 329 # The hash in <tt>local_assigns</tt> is made available as local variables. 360 def render_template(template _extension, template, file_path = nil, local_assigns = {}) #:nodoc:361 handler = self.class.handler_class_for_extension(template_extension).new(self)362 @current_render_extension = template _extension330 def render_template(template) #:nodoc: 331 handler = template.handler 332 @current_render_extension = template.extension 363 333 364 334 if handler.compilable? 365 compile_and_render_template(handler, template , file_path, local_assigns)335 compile_and_render_template(handler, template) 366 336 else 367 template ||= handler.read_template_file(file_path, template_extension) # Make sure that a lazyily-read template is loaded. 368 handler.render(template, local_assigns) 337 handler.render(template.source, template.locals) 369 338 end 370 339 end … … 408 377 # will only be read if it has to be compiled. 409 378 # 410 def compile_and_render_template(handler, template = nil, file_path = nil, local_assigns = {}) #:nodoc: 411 # convert string keys to symbols if requested 412 local_assigns = local_assigns.symbolize_keys if @@local_assigns_support_string_keys 413 379 def compile_and_render_template(handler, template) #:nodoc: 414 380 # compile the given template, if necessary 415 handler.compile_template(template , file_path, local_assigns)381 handler.compile_template(template) 416 382 417 383 # Get the method name for this template and run it 418 method_name = @@method_names[ file_path || template]384 method_name = @@method_names[template.method_key] 419 385 evaluate_assigns 420 386 421 send(method_name, local_assigns) do |*name|387 send(method_name, template.locals) do |*name| 422 388 instance_variable_get "@content_for_#{name.first || 'layout'}" 423 389 end trunk/actionpack/lib/action_view/template_error.rb
r8743 r8805 7 7 attr_reader :original_exception 8 8 9 def initialize( base_path, file_path, assigns, source, original_exception)10 @base_path , @assigns, @source, @original_exception =11 base_path, assigns.dup,source, original_exception12 @file_path = file_path9 def initialize(template, assigns, original_exception) 10 @base_path = template.base_path_for_exception 11 @assigns, @source, @original_exception = assigns.dup, template.source, original_exception 12 @file_path = template.filename 13 13 @backtrace = compute_backtrace 14 14 end trunk/actionpack/lib/action_view/template_handler.rb
r8756 r8805 31 31 def cache_fragment(block, name = {}, options = nil) 32 32 end 33 34 # This method reads a template file.35 def read_template_file(template_path, extension)36 File.read(template_path)37 end38 33 end 39 34 end trunk/actionpack/lib/action_view/template_handlers/compilable.rb
r8756 r8805 27 27 28 28 # Compile and evaluate the template's code 29 def compile_template(template , file_name, local_assigns)30 return unless compile_template?(template , file_name, local_assigns)29 def compile_template(template) 30 return unless compile_template?(template) 31 31 32 template ||= read_template_file(file_name, nil) 33 34 render_symbol = assign_method_name(template, file_name) 35 render_source = create_template_source(template, render_symbol, local_assigns.keys) 32 render_symbol = assign_method_name(template) 33 render_source = create_template_source(template, render_symbol) 36 34 line_offset = self.template_args[render_symbol].size + self.line_offset 37 35 38 36 begin 39 file_name = 'compiled-template' if file_name.blank?37 file_name = template.filename || 'compiled-template' 40 38 ActionView::Base::CompiledTemplates.module_eval(render_source, file_name, -line_offset) 41 39 rescue Exception => e # errors from template code … … 46 44 end 47 45 48 raise ActionView::TemplateError.new(@view.finder.extract_base_path_from(file_name) || 49 @view.finder.view_paths.first, file_name || template, @view.assigns, template, e) 46 raise ActionView::TemplateError.new(template, @view.assigns, e) 50 47 end 51 48 … … 60 57 # if local_assigns has a new key, which isn't supported by the compiled code yet, 61 58 # or if the file has changed on disk and checking file mods hasn't been disabled. 62 def compile_template?(template , file_name, local_assigns)63 method_key = file_name || template59 def compile_template?(template) 60 method_key = template.method_key 64 61 render_symbol = @view.method_names[method_key] 65 62 66 63 compile_time = self.compile_time[render_symbol] 67 if compile_time && supports_local_assigns?(render_symbol, local_assigns)68 if file_name && !@view.cache_template_loading69 template_changed_since?( file_name, compile_time)64 if compile_time && supports_local_assigns?(render_symbol, template.locals) 65 if template.filename && !@view.cache_template_loading 66 template_changed_since?(template.filename, compile_time) 70 67 end 71 68 else … … 74 71 end 75 72 76 def assign_method_name(template, file_name) 77 method_key = file_name || template 78 @view.method_names[method_key] ||= compiled_method_name(template, file_name) 73 def assign_method_name(template) 74 @view.method_names[template.method_key] ||= compiled_method_name(template) 79 75 end 80 76 81 def compiled_method_name(template , file_name)82 ['_run', self.class.to_s.demodulize.underscore, compiled_method_name_file_path_segment( file_name)].compact.join('_').to_sym77 def compiled_method_name(template) 78 ['_run', self.class.to_s.demodulize.underscore, compiled_method_name_file_path_segment(template.filename)].compact.join('_').to_sym 83 79 end 84 80 … … 95 91 96 92 # Method to create the source code for a given template. 97 def create_template_source(template, render_symbol , locals)98 body = compile(template )93 def create_template_source(template, render_symbol) 94 body = compile(template.source) 99 95 100 96 self.template_args[render_symbol] ||= {} 101 locals_keys = self.template_args[render_symbol].keys | locals97 locals_keys = self.template_args[render_symbol].keys | template.locals.keys 102 98 self.template_args[render_symbol] = locals_keys.inject({}) { |h, k| h[k] = true; h } 103 99 trunk/actionpack/test/controller/custom_handler_test.rb
r8624 r8805 21 21 22 22 def test_custom_render 23 result = @view.render_template( "foo", "hello <%= one %>", nil, :one => "two" ) 23 template = ActionView::Template.new(@view, "hello <%= one %>", false, { :one => "two" }, true, "foo") 24 25 result = @view.render_template(template) 24 26 assert_equal( 25 27 [ "hello <%= one %>", { :one => "two" }, @view ], … … 28 30 29 31 def test_custom_render2 30 result = @view.render_template( "foo2", "hello <%= one %>", nil, :one => "two" ) 32 template = ActionView::Template.new(@view, "hello <%= one %>", false, { :one => "two" }, true, "foo2") 33 result = @view.render_template(template) 31 34 assert_equal( 32 35 [ "hello <%= one %>", { :one => "two" }, @view ], … … 36 39 def test_unhandled_extension 37 40 # uses the ERb handler by default if the extension isn't recognized 38 result = @view.render_template( "bar", "hello <%= one %>", nil, :one => "two" ) 41 template = ActionView::Template.new(@view, "hello <%= one %>", false, { :one => "two" }, true, "bar") 42 result = @view.render_template(template) 39 43 assert_equal "hello two", result 40 44 end trunk/actionpack/test/controller/render_test.rb
r8744 r8805 139 139 render :inline => "<%= 'Goodbye, ' + local_name %>", 140 140 :locals => { :local_name => name } 141 end142 143 def accessing_local_assigns_in_inline_template_with_string_keys144 name = params[:local_name]145 ActionView::Base.local_assigns_support_string_keys = true146 render :inline => "<%= 'Goodbye, ' + local_name %>",147 :locals => { "local_name" => name }148 ActionView::Base.local_assigns_support_string_keys = false149 141 end 150 142 … … 388 380 end 389 381 390 def test_accessing_local_assigns_in_inline_template_with_string_keys391 get :accessing_local_assigns_in_inline_template_with_string_keys, :local_name => "Local David"392 assert_equal "Goodbye, Local David", @response.body393 end394 395 382 def test_render_200_should_set_etag 396 383 get :render_hello_world_from_variable trunk/actionpack/test/template/compiled_templates_test.rb
r8689 r8805 88 88 v.cache_template_loading = false 89 89 90 ta = ActionView::Template.new(v, @a, false, {}) 91 tb = ActionView::Template.new(v, @b, false, {}) 92 ts = ActionView::Template.new(v, @s, false, {}) 93 90 94 @handler_class = ActionView::Base.handler_class_for_extension(:rhtml) 91 95 @handler = @handler_class.new(v) … … 100 104 assert @handler.send(:template_changed_since?, @s, t) unless windows 101 105 102 assert @handler.send(:compile_template?, nil, @a, {})103 assert @handler.send(:compile_template?, nil, @b, {})104 assert @handler.send(:compile_template?, nil, @s, {}) unless windows106 assert @handler.send(:compile_template?, ta) 107 assert @handler.send(:compile_template?, tb) 108 assert @handler.send(:compile_template?, ts) unless windows 105 109 106 110 # All templates are rendered at t+2 107 111 Time.expects(:now).times(windows ? 2 : 3).returns(t + 2.seconds) 108 v.send(:compile_and_render_template, @handler, '', @a)109 v.send(:compile_and_render_template, @handler, '', @b)110 v.send(:compile_and_render_template, @handler, '', @s) unless windows112 v.send(:compile_and_render_template, @handler, ta) 113 v.send(:compile_and_render_template, @handler, tb) 114 v.send(:compile_and_render_template, @handler, ts) unless windows 111 115 a_n = v.method_names[@a] 112 116 b_n = v.method_names[@b] … … 123 127 assert !@handler.send(:template_changed_since?, @b, @handler.compile_time[b_n]) 124 128 assert !@handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows 125 assert !@handler.send(:compile_template?, nil, @a, {})126 assert !@handler.send(:compile_template?, nil, @b, {})127 assert !@handler.send(:compile_template?, nil, @s, {}) unless windows128 v.send(:compile_and_render_template, @handler, '', @a)129 v.send(:compile_and_render_template, @handler, '', @b)130 v.send(:compile_and_render_template, @handler, '', @s) unless windows129 assert !@handler.send(:compile_template?, ta) 130 assert !@handler.send(:compile_template?, tb) 131 assert !@handler.send(:compile_template?, ts) unless windows 132 v.send(:compile_and_render_template, @handler, ta) 133 v.send(:compile_and_render_template, @handler, tb) 134 v.send(:compile_and_render_template, @handler, ts) unless windows 131 135 # none of the files have changed since last compile 132 136 assert @handler.compile_time[a_n] < t + 3.seconds … … 145 149 assert !@handler.send(:template_changed_since?, @b, @handler.compile_time[b_n]) 146 150 assert @handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows 147 assert !@handler.send(:compile_template?, nil, @a, {})148 assert !@handler.send(:compile_template?, nil, @b, {})149 assert @handler.send(:compile_template?, nil, @s, {}) unless windows151 assert !@handler.send(:compile_template?, ta) 152 assert !@handler.send(:compile_template?, tb) 153 assert @handler.send(:compile_template?, ts) unless windows 150 154 151 155 # Only the symlink template gets rendered at t+3 152 156 Time.stubs(:now).returns(t + 3.seconds) unless windows 153 v.send(:compile_and_render_template, @handler, '', @a)154 v.send(:compile_and_render_template, @handler, '', @b)155 v.send(:compile_and_render_template, @handler, '', @s) unless windows157 v.send(:compile_and_render_template, @handler, ta) 158 v.send(:compile_and_render_template, @handler, tb) 159 v.send(:compile_and_render_template, @handler, ts) unless windows 156 160 # the symlink has changed since last compile 157 161 assert @handler.compile_time[a_n] < t + 3.seconds … … 171 175 assert @handler.send(:template_changed_since?, @b, @handler.compile_time[b_n]) 172 176 assert @handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows 173 assert !@handler.send(:compile_template?, nil, @a, {})174 assert @handler.send(:compile_template?, nil, @b, {})175 assert @handler.send(:compile_template?, nil, @s, {}) unless windows177 assert !@handler.send(:compile_template?, ta) 178 assert @handler.send(:compile_template?, tb) 179 assert @handler.send(:compile_template?, ts) unless windows 176 180 177 181 Time.expects(:now).times(windows ? 1 : 2).returns(t + 5.seconds) 178 v.send(:compile_and_render_template, @handler, '', @a)179 v.send(:compile_and_render_template, @handler, '', @b)180 v.send(:compile_and_render_template, @handler, '', @s) unless windows182 v.send(:compile_and_render_template, @handler, ta) 183 v.send(:compile_and_render_template, @handler, tb) 184 v.send(:compile_and_render_template, @handler, ts) unless windows 181 185 # the file at the end of the symlink has changed since last compile 182 186 # both the symlink and the file at the end of it should be recompiled