Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Stopped the massive bleeding of concerns into ActionController::Base.…
… Base no longer knows about flash, filters, or components. This may well have introduced some instability, please do test with apps, especially the ones using components. [DHH]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3580 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information
dhh committed Feb 12, 2006
1 parent 838ec41 commit 050c396
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 107 deletions.
8 changes: 4 additions & 4 deletions actionpack/lib/action_controller.rb
Expand Up @@ -38,30 +38,30 @@
require 'action_controller/deprecated_redirects'
require 'action_controller/rescue'
require 'action_controller/benchmarking'
require 'action_controller/flash'
require 'action_controller/filters'
require 'action_controller/layout'
require 'action_controller/flash'
require 'action_controller/dependencies'
require 'action_controller/pagination'
require 'action_controller/scaffolding'
require 'action_controller/helpers'
require 'action_controller/cookies'
require 'action_controller/cgi_process'
require 'action_controller/caching'
require 'action_controller/components'
require 'action_controller/verification'
require 'action_controller/streaming'
require 'action_controller/session_management'
require 'action_controller/components'
require 'action_controller/macros/auto_complete'
require 'action_controller/macros/in_place_editing'

require 'action_view'
ActionController::Base.template_class = ActionView::Base

ActionController::Base.class_eval do
include ActionController::Flash
include ActionController::Filters
include ActionController::Layout
include ActionController::Flash
include ActionController::Benchmarking
include ActionController::Rescue
include ActionController::Dependencies
Expand All @@ -70,10 +70,10 @@
include ActionController::Helpers
include ActionController::Cookies
include ActionController::Caching
include ActionController::Components
include ActionController::Verification
include ActionController::Streaming
include ActionController::SessionManagement
include ActionController::Components
include ActionController::Macros::AutoComplete
include ActionController::Macros::InPlaceEditing
end
75 changes: 39 additions & 36 deletions actionpack/lib/action_controller/base.rb
Expand Up @@ -305,8 +305,8 @@ class Base

class << self
# Factory for the standard create, process loop where the controller is discarded after processing.
def process(request, response, parent_controller = nil) #:nodoc:
new(parent_controller).process(request, response)
def process(request, response) #:nodoc:
new.process(request, response)
end

# Converts the class name from something like "OneModule::TwoModule::NeatController" to "NeatController".
Expand Down Expand Up @@ -347,42 +347,20 @@ def hide_action(*names)
end

public
# If this controller was instantiated to process a component request,
# +parent_controller+ points to the instantiator of this controller.
attr_reader :parent_controller

# Create a new controller instance.
def initialize(parent_controller=nil) #:nodoc:
@parent_controller = parent_controller
end

# Extracts the action_name from the request parameters and performs that action.
def process(request, response, method = :perform_action, *arguments) #:nodoc:
initialize_template_class(response)
assign_shortcuts(request, response)

my_flash = flash # calling flash creates @flash
if my_parent = @parent_controller
# only discard flash if this controller isn't a component request controller
my_flash.discard
end

initialize_current_url
@action_name = params['action'] || 'index'
@variables_added = nil
@before_filter_chain_aborted = false

log_processing if logger
action_name(:refresh)
forget_variables_added_to_assigns

log_processing
send(method, *arguments)
@response

return response
ensure
unless my_parent
unless @before_filter_chain_aborted
my_flash.sweep
clear_persistent_model_associations
end
close_session
end
process_cleanup
end

# Returns a URL that has been rewritten according to the options hash and the defined Routes.
Expand Down Expand Up @@ -472,6 +450,15 @@ def controller_name
self.class.controller_name
end

# Returns the name of the current action
def action_name(refresh = false)
if @action_name.nil? || refresh
@action_name = (params['action'] || 'index')
end

@action_name
end

def session_enabled?
request.session_options[:disabled] != false
end
Expand Down Expand Up @@ -668,9 +655,11 @@ def render(options = nil, deprecated_status = nil, &block) #:doc:
# of sending it as the response body to the browser.
def render_to_string(options = nil, &block) #:doc:
result = render(options, &block)

erase_render_results
@variables_added = nil
@template.instance_variable_set("@assigns_added", nil)
forget_variables_added_to_assigns
reset_variables_added_to_assigns

result
end

Expand Down Expand Up @@ -886,9 +875,11 @@ def initialize_current_url
end

def log_processing
logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
logger.info " Session ID: #{@session.session_id}" if @session and @session.respond_to?(:session_id)
logger.info " Parameters: #{@params.inspect}"
if logger
logger.info "\n\nProcessing #{controller_class_name}\##{action_name} (for #{request_origin}) [#{request.method.to_s.upcase}]"
logger.info " Session ID: #{@session.session_id}" if @session and @session.respond_to?(:session_id)
logger.info " Parameters: #{@params.inspect}"
end
end

def perform_action
Expand Down Expand Up @@ -921,6 +912,14 @@ def add_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
@@protected_variables_cache ||= protected_instance_variables.inject({}) { |h, k| h[k] = true; h }
Expand Down Expand Up @@ -993,5 +992,9 @@ def strip_out_controller!(path)
def template_path_includes_controller?(path)
path.to_s['/'] && self.class.controller_path.split('/')[-1] == path.split('/')[0]
end

def process_cleanup
close_session
end
end
end
4 changes: 2 additions & 2 deletions actionpack/lib/action_controller/benchmarking.rb
Expand Up @@ -4,9 +4,9 @@ module ActionController #:nodoc:
# The benchmarking module times the performance of actions and reports to the logger. If the Active Record
# package has been included, a separate timing section for database calls will be added as well.
module Benchmarking #:nodoc:
def self.append_features(base)
super
def self.included(base)
base.extend(ClassMethods)

base.class_eval do
alias_method :perform_action_without_benchmark, :perform_action
alias_method :perform_action, :perform_action_with_benchmark
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_controller/caching.rb
Expand Up @@ -8,9 +8,9 @@ module ActionController #:nodoc:
#
# Note: To turn off all caching and sweeping, set Base.perform_caching = false.
module Caching
def self.append_features(base) #:nodoc:
super
def self.included(base) #:nodoc:
base.send(:include, Pages, Actions, Fragments, Sweeping)

base.class_eval do
@@perform_caching = true
cattr_accessor :perform_caching
Expand Down
65 changes: 51 additions & 14 deletions actionpack/lib/action_controller/components.rb
Expand Up @@ -36,17 +36,36 @@ module ActionController #:nodoc:
# So to repeat: Components are a special-purpose approach that can often be replaced with better use of partials and filters.
module Components
def self.included(base) #:nodoc:
base.send :include, InstanceMethods
base.extend(ClassMethods)
base.send(:include, InstanceMethods)

base.helper do
def render_component(options)
@controller.send(:render_component_as_string, options)
end
end

base.class_eval do
alias_method :process_cleanup_without_components, :process_cleanup
alias_method :process_cleanup, :process_cleanup_with_components

alias_method :set_session_options_without_components, :set_session_options
alias_method :set_session_options, :set_session_options_with_components
end

# If this controller was instantiated to process a component request,
# +parent_controller+ points to the instantiator of this controller.
base.send :attr_accessor, :parent_controller
end

module ClassMethods
# Track parent controller to identify component requests
def process_with_components(request, response, parent_controller = nil) #:nodoc:
controller = new
controller.parent_controller = parent_controller
controller.process(request, response)
end

# Set the template root to be one directory behind the root dir of the controller. Examples:
# /code/weblog/components/admin/users_controller.rb with Admin::UsersController
# will use /code/weblog/components as template root
Expand All @@ -64,6 +83,12 @@ def uses_component_template_root
end

module InstanceMethods
# Extracts the action_name from the request parameters and performs that action.
def process_with_components(request, response, method = :perform_action, *arguments) #:nodoc:
flash.discard if component_request?
process_without_components(request, response, method, *arguments)
end

protected
# Renders the component specified as the response for the current method
def render_component(options) #:doc:
Expand All @@ -90,8 +115,8 @@ def component_response(options, reuse_response)
klass = component_class(options)
request = request_for_component(klass.controller_name, options)
response = reuse_response ? @response : @response.dup
klass.process(request, response, self)

klass.process_with_components(request, response, self)
end

# determine the controller class for the component request
Expand All @@ -118,18 +143,30 @@ def request_for_component(controller_name, options)
)

request
end
end

def component_logging(options)
if logger
logger.info "Start rendering component (#{options.inspect}): "
result = yield
logger.info "\n\nEnd of component rendering"
result
else
yield
end
end
def component_logging(options)
if logger
logger.info "Start rendering component (#{options.inspect}): "
result = yield
logger.info "\n\nEnd of component rendering"
result
else
yield
end
end

def component_request?
!@parent_controller.nil?
end

def set_session_options_with_components(request)
set_session_options_without_components(request) unless component_request?
end

def process_cleanup_with_components
process_cleanup_without_components unless component_request?
end
end
end
end
25 changes: 21 additions & 4 deletions actionpack/lib/action_controller/filters.rb
Expand Up @@ -335,23 +335,35 @@ def condition_hash(filters, *actions)
end

module InstanceMethods # :nodoc:
def self.append_features(base)
super
base.class_eval {
def self.included(base)
base.class_eval do
alias_method :perform_action_without_filters, :perform_action
alias_method :perform_action, :perform_action_with_filters
}

alias_method :process_without_filters, :process
alias_method :process, :process_with_filters

alias_method :process_cleanup_without_filters, :process_cleanup
alias_method :process_cleanup, :process_cleanup_with_filters
end
end

def perform_action_with_filters
before_action_result = before_action

unless before_action_result == false || performed?
perform_action_without_filters
after_action
end

@before_filter_chain_aborted = (before_action_result == false)
end

def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc:
@before_filter_chain_aborted = false
process_without_filters(request, response, method, *arguments)
end

# Calls all the defined before-filter filters, which are added by using "before_filter :method".
# If any of the filters return false, no more filters will be executed and the action is aborted.
def before_action #:doc:
Expand All @@ -368,6 +380,7 @@ def after_action #:doc:
def call_filters(filters)
filters.each do |filter|
next if action_exempted?(filter)

filter_result = case
when filter.is_a?(Symbol)
self.send(filter)
Expand Down Expand Up @@ -405,6 +418,10 @@ def action_exempted?(filter)
ea.include?(action_name)
end
end

def process_cleanup_with_filters
process_cleanup_without_filters unless @before_filter_chain_aborted
end
end
end
end

0 comments on commit 050c396

Please sign in to comment.