aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/lib/abstract_controller/helpers.rb10
-rw-r--r--actionpack/lib/action_view/base.rb34
2 files changed, 31 insertions, 13 deletions
diff --git a/actionpack/lib/abstract_controller/helpers.rb b/actionpack/lib/abstract_controller/helpers.rb
index 04eaa02441..f3072fad74 100644
--- a/actionpack/lib/abstract_controller/helpers.rb
+++ b/actionpack/lib/abstract_controller/helpers.rb
@@ -4,8 +4,16 @@ module AbstractController
include RenderingController
+ def self.next_serial
+ @helper_serial ||= 0
+ @helper_serial += 1
+ end
+
included do
extlib_inheritable_accessor(:_helpers) { Module.new }
+ extlib_inheritable_accessor(:_helper_serial) do
+ AbstractController::Helpers.next_serial
+ end
end
module ClassMethods
@@ -58,6 +66,8 @@ module AbstractController
# of the helper module. Any methods defined in the block
# will be helpers.
def helper(*args, &block)
+ self._helper_serial = AbstractController::Helpers.next_serial + 1
+
args.flatten.each do |arg|
case arg
when Module
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c3361c9367..c171a5a8f5 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -164,6 +164,9 @@ module ActionView #:nodoc:
#
# See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details.
class Base
+ module Subclasses
+ end
+
include Helpers, Rendering, Partials, ::ERB::Util
extend ActiveSupport::Memoizable
@@ -212,30 +215,35 @@ module ActionView #:nodoc:
ActionView::PathSet.new(Array(value))
end
+ extlib_inheritable_accessor :helpers
attr_reader :helpers
- class ProxyModule < Module
- def initialize(receiver)
- @receiver = receiver
- end
+ def self.for_controller(controller)
+ @views ||= {}
- def include(*args)
- super(*args)
- @receiver.extend(*args)
- end
- end
+ # TODO: Decouple this so helpers are a separate concern in AV just like
+ # they are in AC.
+ if controller.class.respond_to?(:_helper_serial)
+ klass = @views[controller.class._helper_serial] ||= Class.new(self) do
+ Subclasses.const_set(controller.class.name.gsub(/::/, '__'), self)
- def self.for_controller(controller)
- new(controller.class.view_paths, {}, controller).tap do |view|
- view.helpers.include(controller._helpers) if controller.respond_to?(:_helpers)
+ if controller.respond_to?(:_helpers)
+ include controller._helpers
+ self.helpers = controller._helpers
+ end
+ end
+ else
+ klass = self
end
+
+ klass.new(controller.class.view_paths, {}, controller)
end
def initialize(view_paths = [], assigns_for_first_render = {}, controller = nil, formats = nil)#:nodoc:
@formats = formats || [:html]
@assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
@controller = controller
- @helpers = ProxyModule.new(self)
+ @helpers = self.class.helpers || Module.new
@_content_for = Hash.new {|h,k| h[k] = "" }
self.view_paths = view_paths
end