diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 7dbc62980a..d12cc41cfa 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -260,10 +260,11 @@ module ActionController #:nodoc: include StatusCodes + cattr_reader :protected_instance_variables # Controller specific instance variables which will not be accessible inside views. - @@protected_view_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller - @action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params - @_flash @_response) + @@protected_instance_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller + @action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params + @_flash @_response) # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets, # and images to a dedicated asset server away from the main web server. Example: @@ -393,10 +394,6 @@ module ActionController #:nodoc: # directive. Values should always be specified as strings. attr_internal :headers - # Holds the hash of variables that are passed on to the template class to be made available to the view. This hash - # is generated by taking a snapshot of all the instance variables in the current scope just before a template is rendered. - attr_accessor :assigns - # Returns the name of the action this controller is processing. attr_accessor :action_name @@ -538,7 +535,6 @@ module ActionController #:nodoc: assign_shortcuts(request, response) initialize_current_url assign_names - forget_variables_added_to_assigns log_processing @@ -893,7 +889,6 @@ module ActionController #:nodoc: render_for_file(template, options[:status], options[:locals] || {}) elsif inline = options[:inline] - add_variables_to_assigns render_for_text(@template.render(options), options[:status]) elsif action_name = options[:action] @@ -911,12 +906,10 @@ module ActionController #:nodoc: elsif options[:partial] options[:partial] = default_template_name if options[:partial] == true - add_variables_to_assigns render_for_text(@template.render(options), options[:status]) elsif options[:update] - add_variables_to_assigns - @template.send! :evaluate_assigns + @template.send! :evaluate_assigns_and_ivars generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block) response.content_type = Mime::JS @@ -937,7 +930,6 @@ module ActionController #:nodoc: render(options, &block) ensure erase_render_results - forget_variables_added_to_assigns reset_variables_added_to_assigns end @@ -1123,7 +1115,6 @@ module ActionController #:nodoc: private def render_for_file(template_path, status = nil, locals = {}) #:nodoc: - add_variables_to_assigns logger.info("Rendering #{template_path}" + (status ? " (#{status})" : '')) if logger render_for_text(@template.render(:file => template_path, :locals => locals), status) end @@ -1160,7 +1151,6 @@ module ActionController #:nodoc: @_session = @_response.session @template = @_response.template - @assigns = @_response.template.assigns @_headers = @_response.headers end @@ -1224,27 +1214,10 @@ module ActionController #:nodoc: hidden_actions end - def add_variables_to_assigns - unless @variables_added - add_instance_variables_to_assigns - @variables_added = true - end - end - - def forget_variables_added_to_assigns - @variables_added = nil - end - def reset_variables_added_to_assigns @template.instance_variable_set("@assigns_added", nil) end - def add_instance_variables_to_assigns - (instance_variable_names - @@protected_view_variables).each do |var| - @assigns[var[1..-1]] = instance_variable_get(var) - end - end - def request_origin # this *needs* to be cached! # otherwise you'd get different results if calling it more than once diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb index fd743ced38..585bd03797 100644 --- a/actionpack/lib/action_controller/layout.rb +++ b/actionpack/lib/action_controller/layout.rb @@ -250,7 +250,6 @@ module ActionController #:nodoc: content_for_layout = render_with_no_layout(options, extra_options, &block) erase_render_results - add_variables_to_assigns @template.instance_variable_set("@content_for_layout", content_for_layout) response.layout = layout status = template_with_options ? options[:status] : nil diff --git a/actionpack/lib/action_controller/rescue.rb b/actionpack/lib/action_controller/rescue.rb index a1a9d68a35..1492c4ec61 100644 --- a/actionpack/lib/action_controller/rescue.rb +++ b/actionpack/lib/action_controller/rescue.rb @@ -177,11 +177,8 @@ module ActionController #:nodoc: # Render detailed diagnostics for unhandled exceptions rescued from # a controller action. def rescue_action_locally(exception) - add_variables_to_assigns @template.instance_variable_set("@exception", exception) @template.instance_variable_set("@rescues_path", File.dirname(rescues_path("stub"))) - @template.send!(:assign_variables_from_controller) - @template.instance_variable_set("@contents", @template.render(:file => template_path_for_local_rescue(exception))) response.content_type = Mime::HTML diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb index a11fa7cd10..1d0254b522 100644 --- a/actionpack/lib/action_controller/test_process.rb +++ b/actionpack/lib/action_controller/test_process.rb @@ -3,6 +3,8 @@ require 'action_controller/test_case' module ActionController #:nodoc: class Base + attr_reader :assigns + # Process a test request called with a TestRequest object. def self.process_test(request) new.process_test(request) @@ -14,7 +16,12 @@ module ActionController #:nodoc: def process_with_test(*args) returning process_without_test(*args) do - add_variables_to_assigns + @assigns = {} + (instance_variable_names - @@protected_instance_variables).each do |var| + value = instance_variable_get(var) + @assigns[var[1..-1]] = value + response.template.assigns[var[1..-1]] = value if response + end end end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index c65048bfa0..ce629d332a 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -343,18 +343,20 @@ module ActionView #:nodoc: private # Evaluate the local assigns and pushes them to the view. - def evaluate_assigns + def evaluate_assigns_and_ivars unless @assigns_added - assign_variables_from_controller + @assigns.each { |key, value| instance_variable_set("@#{key}", value) } + + if @controller + variables = @controller.instance_variables + variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables) + variables.each {|name| instance_variable_set(name, @controller.instance_variable_get(name)) } + end + @assigns_added = true end end - # Assigns instance variables from the controller to the view. - def assign_variables_from_controller - @assigns.each { |key, value| instance_variable_set("@#{key}", value) } - end - def set_controller_content_type(content_type) if controller.respond_to?(:response) controller.response.content_type ||= content_type diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb index fa45edd436..5d950e336e 100644 --- a/actionpack/lib/action_view/renderable.rb +++ b/actionpack/lib/action_view/renderable.rb @@ -29,7 +29,7 @@ module ActionView view._first_render ||= self view._last_render = self - view.send(:evaluate_assigns) + view.send(:evaluate_assigns_and_ivars) view.send(:set_controller_content_type, mime_type) if respond_to?(:mime_type) view.send(method_name(local_assigns), local_assigns) do |*names| diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb index 3652c482f1..55fee226e2 100644 --- a/actionpack/test/controller/filters_test.rb +++ b/actionpack/test/controller/filters_test.rb @@ -111,15 +111,15 @@ class FilterTest < Test::Unit::TestCase end class OnlyConditionProcController < ConditionalFilterController - before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true } + before_filter(:only => :show) {|c| c.instance_variable_set(:"@ran_proc_filter", true) } end class ExceptConditionProcController < ConditionalFilterController - before_filter(:except => :show_without_filter) {|c| c.assigns["ran_proc_filter"] = true } + before_filter(:except => :show_without_filter) {|c| c.instance_variable_set(:"@ran_proc_filter", true) } end class ConditionalClassFilter - def self.filter(controller) controller.assigns["ran_class_filter"] = true end + def self.filter(controller) controller.instance_variable_set(:"@ran_class_filter", true) end end class OnlyConditionClassController < ConditionalFilterController @@ -131,7 +131,7 @@ class FilterTest < Test::Unit::TestCase end class AnomolousYetValidConditionController < ConditionalFilterController - before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true} + before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.instance_variable_set(:"@ran_proc_filter1", true)}, :except => :show_without_filter) { |c| c.instance_variable_set(:"@ran_proc_filter2", true)} end class ConditionalOptionsFilter < ConditionalFilterController @@ -225,16 +225,16 @@ class FilterTest < Test::Unit::TestCase end class ProcController < PrependingController - before_filter(proc { |c| c.assigns["ran_proc_filter"] = true }) + before_filter(proc { |c| c.instance_variable_set(:"@ran_proc_filter", true) }) end class ImplicitProcController < PrependingController - before_filter { |c| c.assigns["ran_proc_filter"] = true } + before_filter { |c| c.instance_variable_set(:"@ran_proc_filter", true) } end class AuditFilter def self.filter(controller) - controller.assigns["was_audited"] = true + controller.instance_variable_set(:"@was_audited", true) end end @@ -242,12 +242,12 @@ class FilterTest < Test::Unit::TestCase def before(controller) @execution_log = "before" controller.class.execution_log << " before aroundfilter " if controller.respond_to? :execution_log - controller.assigns["before_ran"] = true + controller.instance_variable_set(:"@before_ran", true) end def after(controller) - controller.assigns["execution_log"] = @execution_log + " and after" - controller.assigns["after_ran"] = true + controller.instance_variable_set(:"@execution_log", @execution_log + " and after") + controller.instance_variable_set(:"@after_ran", true) controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log end end @@ -726,9 +726,9 @@ end class ControllerWithProcFilter < PostsController around_filter(:only => :no_raise) do |c,b| - c.assigns['before'] = true + c.instance_variable_set(:"@before", true) b.call - c.assigns['after'] = true + c.instance_variable_set(:"@after", true) end end