From a156576ce9aa75e8d455ed18052fb88d7ed614bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sat, 18 Dec 2010 09:38:41 +0100 Subject: [PATCH] Fix an issue causing infinite redirects in production, closes #720 --- lib/devise.rb | 24 ++++++++++++++++++++++ lib/devise/controllers/internal_helpers.rb | 7 +++++-- lib/devise/rails/routes.rb | 1 + test/rails_app/config/application.rb | 5 +++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/devise.rb b/lib/devise.rb index 724b75e6..0d9aee27 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -204,6 +204,11 @@ module Devise @@warden_config = nil @@warden_config_block = nil + # Store whether the route file was already loaded. + mattr_accessor :routes_loaded + @@routes_loaded = false + @@routes_prepare = [] + # Default way to setup Devise. Run rails generate devise_install to create # a fresh initializer with all configuration values. def self.setup @@ -359,6 +364,25 @@ module Devise def self.friendly_token ActiveSupport::SecureRandom.base64(44).tr('+/=', 'xyz') end + + # Store a block to be executed only after the routes are loaded. + # Required on config.cache_classes environment as a class may be + # loaded to early and then some configuration wouldn't apply. + def self.routes_prepare + if Rails.application.config.cache_classes || !routes_loaded + @@routes_prepare << Proc.new + else + yield + end + end + + # Invoke the stored routes prepare blocks and set routes_loaded to true. + def self.call_routes_prepare! + while block = @@routes_prepare.shift + block.call + end + @routes_loaded = true + end end require 'warden' diff --git a/lib/devise/controllers/internal_helpers.rb b/lib/devise/controllers/internal_helpers.rb index 5a1d99e2..fc501858 100644 --- a/lib/devise/controllers/internal_helpers.rb +++ b/lib/devise/controllers/internal_helpers.rb @@ -16,12 +16,15 @@ module Devise helper_method *helpers prepend_before_filter :is_devise_resource? - skip_before_filter *Devise.mappings.keys.map { |m| :"authenticate_#{m}!" } + + Devise.routes_prepare do + skip_before_filter *Devise.mappings.keys.map { |m| :"authenticate_#{m}!" } + end end # Gets the actual resource stored in the instance variable def resource - instance_variable_get(:"@#{resource_name}") + instance_variable_get("@#{resource_name}") end # Proxy to devise map name diff --git a/lib/devise/rails/routes.rb b/lib/devise/rails/routes.rb index 7ac74926..ef7b0d08 100644 --- a/lib/devise/rails/routes.rb +++ b/lib/devise/rails/routes.rb @@ -4,6 +4,7 @@ module ActionDispatch::Routing # need devise_for mappings already declared to create filters and helpers. def finalize_with_devise! finalize_without_devise! + Devise.call_routes_prepare! Devise.configure_warden! end alias_method_chain :finalize!, :devise diff --git a/test/rails_app/config/application.rb b/test/rails_app/config/application.rb index 63897c78..8b8b5e5c 100644 --- a/test/rails_app/config/application.rb +++ b/test/rails_app/config/application.rb @@ -31,5 +31,10 @@ module RailsApp config.filter_parameters << :password config.action_mailer.default_url_options = { :host => "localhost:3000" } + + # This was used to break devise in some situations + config.to_prepare do + Devise::SessionsController.layout "application" + end end end