diff --git a/lib/devise.rb b/lib/devise.rb index e1122053..da4bb8e1 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -397,6 +397,12 @@ module Devise Rails::VERSION::STRING[0,3] != "3.0" end + # Renegeres url helpers considering Devise.mapping + def self.regenerate_helpers! + Devise::Controllers::UrlHelpers.remove_helpers! + Devise::Controllers::UrlHelpers.generate_helpers! + end + # A method used internally to setup warden manager from the Rails initialize # block. def self.configure_warden! #:nodoc: diff --git a/lib/devise/controllers/url_helpers.rb b/lib/devise/controllers/url_helpers.rb index b1bb46da..82d4af2b 100644 --- a/lib/devise/controllers/url_helpers.rb +++ b/lib/devise/controllers/url_helpers.rb @@ -18,22 +18,31 @@ module Devise # # Those helpers are added to your ApplicationController. module UrlHelpers - - Devise::URL_HELPERS.each do |module_name, actions| - [:path, :url].each do |path_or_url| - actions.each do |action| - action = action ? "#{action}_" : "" - - class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1 - def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args) - scope = Devise::Mapping.find_scope!(resource_or_scope) - send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args) - end - URL_HELPERS - end + def self.remove_helpers! + self.instance_methods.map(&:to_s).grep(/_(url|path)$/).each do |method| + remove_method method end end + def self.generate_helpers! + mappings = Devise.mappings.values.map(&:used_routes).flatten.uniq + routes = Devise::URL_HELPERS.slice(*mappings) + + routes.each do |module_name, actions| + [:path, :url].each do |path_or_url| + actions.each do |action| + action = action ? "#{action}_" : "" + + class_eval <<-URL_HELPERS, __FILE__, __LINE__ + 1 + def #{action}#{module_name}_#{path_or_url}(resource_or_scope, *args) + scope = Devise::Mapping.find_scope!(resource_or_scope) + send("#{action}\#{scope}_#{module_name}_#{path_or_url}", *args) + end + URL_HELPERS + end + end + end + end end end end diff --git a/lib/devise/mapping.rb b/lib/devise/mapping.rb index c833a136..d39ad55e 100644 --- a/lib/devise/mapping.rb +++ b/lib/devise/mapping.rb @@ -22,7 +22,8 @@ module Devise # # is the modules included in the class # class Mapping #:nodoc: - attr_reader :singular, :scoped_path, :path, :controllers, :path_names, :class_name, :sign_out_via, :format + attr_reader :singular, :scoped_path, :path, :controllers, :path_names, + :class_name, :sign_out_via, :format, :used_routes alias :name :singular # Receives an object and find a scope for it. If a scope cannot be found, @@ -72,6 +73,12 @@ module Devise @sign_out_via = options[:sign_out_via] || Devise.sign_out_via @format = options[:format] + + @used_routes = self.routes + if options.has_key?(:only) + @used_routes = Array(options.delete(:only)).map { |s| s.to_s.singularize.to_sym } & @used_routes + end + @used_routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym } end # Return modules for the mapping. diff --git a/lib/devise/rails/routes.rb b/lib/devise/rails/routes.rb index c6db7d5a..c7215507 100644 --- a/lib/devise/rails/routes.rb +++ b/lib/devise/rails/routes.rb @@ -5,6 +5,7 @@ module ActionDispatch::Routing def finalize_with_devise! finalize_without_devise! Devise.configure_warden! + Devise.regenerate_helpers! end alias_method_chain :finalize!, :devise end @@ -188,11 +189,7 @@ module ActionDispatch::Routing raise_no_devise_method_error!(mapping.class_name) end - routes = mapping.routes - if options.has_key?(:only) - routes = Array(options.delete(:only)).map { |s| s.to_s.singularize.to_sym } & mapping.routes - end - routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym } + routes = mapping.used_routes devise_scope mapping.name do yield if block_given?