aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/abstract_controller
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/abstract_controller')
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb10
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb33
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb64
3 files changed, 67 insertions, 40 deletions
diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb
index f875213afb..53cf6b3931 100644
--- a/actionpack/lib/abstract_controller/helpers.rb
+++ b/actionpack/lib/abstract_controller/helpers.rb
@@ -6,16 +6,10 @@ module AbstractController
include Rendering
- def self.next_serial
- @helper_serial ||= 0
- @helper_serial += 1
- end
-
included do
- class_attribute :_helpers, :_helper_serial
+ class_attribute :_helpers
delegate :_helpers, :to => :'self.class'
self._helpers = Module.new
- self._helper_serial = ::AbstractController::Helpers.next_serial
end
module ClassMethods
@@ -95,8 +89,6 @@ module AbstractController
# helper(:three, BlindHelper) { def mice() 'mice' end }
#
def helper(*args, &block)
- self._helper_serial = AbstractController::Helpers.next_serial + 1
-
modules_for_helpers(args).each do |mod|
add_template_helper(mod)
end
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb
index 95a6101109..319472c937 100644
--- a/actionpack/lib/abstract_controller/layouts.rb
+++ b/actionpack/lib/abstract_controller/layouts.rb
@@ -1,3 +1,5 @@
+require "active_support/core_ext/module/remove_method"
+
module AbstractController
# Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in
# repeated setups. The inclusion pattern has pages that look like this:
@@ -182,7 +184,9 @@ module AbstractController
#
# ==== Returns
# Boolean:: True if the action has a layout, false otherwise.
- def _action_has_layout?
+ def action_has_layout?
+ return unless super
+
conditions = _layout_conditions
if only = conditions[:only]
@@ -237,6 +241,8 @@ module AbstractController
# name, return that string. Otherwise, use the superclass'
# layout (which might also be implied)
def _write_layout_method
+ remove_possible_method(:_layout)
+
case defined?(@_layout) ? @_layout : nil
when String
self.class_eval %{def _layout; #{@_layout.inspect} end}
@@ -284,15 +290,20 @@ module AbstractController
layout = options.key?(:layout) ? options.delete(:layout) : :default
value = _layout_for_option(layout)
options[:layout] = (value =~ /\blayouts/ ? value : "layouts/#{value}") if value
-
- # TODO Layout for partials should be handled here, because inside the
- # partial renderer it looks for the layout as a partial.
- if options.key?(:partial) && options[:layout]
- options[:layout] = view_context.find_layout(options[:layout])
- end
end
end
+ attr_writer :action_has_layout
+
+ def initialize(*)
+ @action_has_layout = true
+ super
+ end
+
+ def action_has_layout?
+ @action_has_layout
+ end
+
private
# This will be overwritten by _write_layout_method
@@ -332,13 +343,13 @@ module AbstractController
# Template:: The template object for the default layout (or nil)
def _default_layout(require_layout = false)
begin
- layout_name = _layout if _action_has_layout?
+ layout_name = _layout if action_has_layout?
rescue NameError => e
raise NoMethodError,
"You specified #{@_layout.inspect} as the layout, but no such method was found"
end
- if require_layout && _action_has_layout? && !layout_name
+ if require_layout && action_has_layout? && !layout_name
raise ArgumentError,
"There was no default layout for #{self.class} in #{view_paths.inspect}"
end
@@ -349,9 +360,5 @@ module AbstractController
def _include_layout?(options)
(options.keys & [:text, :inline, :partial]).empty? || options.key?(:layout)
end
-
- def _action_has_layout?
- true
- end
end
end
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index 16664098e5..b251bd6405 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -32,7 +32,6 @@ module AbstractController
module Rendering
extend ActiveSupport::Concern
- include AbstractController::Assigns
include AbstractController::ViewPaths
# Overwrite process to setup I18n proxy.
@@ -43,17 +42,48 @@ module AbstractController
I18n.config = old_config
end
+ module ClassMethods
+ def view_context_class
+ @view_context_class ||= begin
+ controller = self
+ Class.new(ActionView::Base) do
+ if controller.respond_to?(:_helpers)
+ include controller._helpers
+
+ if controller.respond_to?(:_router)
+ include controller._router.url_helpers
+ end
+
+ # TODO: Fix RJS to not require this
+ self.helpers = controller._helpers
+ end
+ end
+ end
+ end
+ end
+
+ attr_writer :view_context_class
+
+ def view_context_class
+ @view_context_class || self.class.view_context_class
+ end
+
+ def initialize(*)
+ @view_context_class = nil
+ super
+ end
+
# An instance of a view class. The default view class is ActionView::Base
#
# The view class must have the following methods:
- # View.for_controller[controller]
+ # View.new[lookup_context, assigns, controller]
# Create a new ActionView instance for a controller
- # View#render_template[options]
+ # View#render[options]
# Returns String with the rendered template
#
# Override this method in a module to change the default behavior.
def view_context
- @_view_context ||= ActionView::Base.for_controller(self)
+ view_context_class.new(lookup_context, view_assigns, self)
end
# Normalize arguments, options and then delegates render_to_body and
@@ -76,13 +106,12 @@ module AbstractController
# :api: plugin
def render_to_string(options={})
_normalize_options(options)
- AbstractController::Rendering.body_to_s(render_to_body(options))
+ render_to_body(options)
end
# Find and renders a template based on the options given.
# :api: private
def _render_template(options) #:nodoc:
- _evaluate_assigns(view_context)
view_context.render(options)
end
@@ -91,20 +120,19 @@ module AbstractController
controller_path
end
- # Return a string representation of a Rack-compatible response body.
- def self.body_to_s(body)
- if body.respond_to?(:to_str)
- body
- else
- strings = []
- body.each { |part| strings << part.to_s }
- body.close if body.respond_to?(:close)
- strings.join
- end
- end
-
private
+ # This method should return a hash with assigns.
+ # You can overwrite this configuration per controller.
+ # :api: public
+ def view_assigns
+ hash = {}
+ variables = instance_variable_names
+ variables -= protected_instance_variables if respond_to?(:protected_instance_variables)
+ variables.each { |name| hash[name.to_s[1..-1]] = instance_variable_get(name) }
+ hash
+ end
+
# Normalize options by converting render "foo" to render :action => "foo" and
# render "foo/bar" to render :file => "foo/bar".
def _normalize_args(action=nil, options={})