From 05678e773fbeca9a0b251e1aad72a573d8ac5a75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Fri, 6 Nov 2009 20:59:36 -0200 Subject: [PATCH] Added support to config.default_url_options. --- CHANGELOG.rdoc | 3 ++- generators/devise_install/templates/devise.rb | 7 +++++++ lib/devise.rb | 5 +++++ lib/devise/controllers/filters.rb | 6 ++++++ lib/devise/mapping.rb | 15 +++++++++++---- lib/devise/rails/routes.rb | 11 ++++++++--- test/controllers/filters_test.rb | 9 +++++++++ test/mapping_test.rb | 9 +++++++-- 8 files changed, 55 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 0eb7f610..41429fde 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -7,7 +7,8 @@ * skip_before_filter added in Devise controllers * Use home_or_root_path on require_no_authentication as well * Added devise_controller?, useful to select or reject filters in ApplicationController - * Allow :path_prefix to be given to devise_for (:path_prefix => "/:locale" is supported) + * Allow :path_prefix to be given to devise_for + * Allow default_url_options to be configured through devise (:path_prefix => "/:locale" is now supported) == 0.4.1 diff --git a/generators/devise_install/templates/devise.rb b/generators/devise_install/templates/devise.rb index 08c4dfe2..8843e7b5 100644 --- a/generators/devise_install/templates/devise.rb +++ b/generators/devise_install/templates/devise.rb @@ -30,4 +30,11 @@ Devise.setup do |config| # end # manager.default_strategies.unshift :twitter_oauth # end + + # Configure default_url_options if you are using dynamic segments in :path_prefix + # for devise_for. + # + # config.default_url_options do + # { :locale => I18n.locale } + # end end diff --git a/lib/devise.rb b/lib/devise.rb index dc11a9d1..717619ce 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -57,6 +57,11 @@ module Devise @warden_config = block end + # Configure default url options to be used within Devise and ActionController. + def default_url_options(&block) + Devise::Mapping.metaclass.send :define_method, :default_url_options, &block + end + # A method used internally to setup warden manager from the Rails initialize # block. def configure_warden_manager(manager) #:nodoc: diff --git a/lib/devise/controllers/filters.rb b/lib/devise/controllers/filters.rb index 8157b400..e6787be3 100644 --- a/lib/devise/controllers/filters.rb +++ b/lib/devise/controllers/filters.rb @@ -8,6 +8,12 @@ module Devise base.class_eval do helper_method :warden, :signed_in?, :devise_controller?, *Devise.mappings.keys.map { |m| [:"current_#{m}", :"#{m}_signed_in?"] }.flatten + + # Use devise default_url_options. We have to declare it here to overwrite + # default definitions. + def default_url_options(options=nil) + Devise::Mapping.default_url_options + end end end diff --git a/lib/devise/mapping.rb b/lib/devise/mapping.rb index 7d13f811..90a088e5 100644 --- a/lib/devise/mapping.rb +++ b/lib/devise/mapping.rb @@ -34,7 +34,12 @@ module Devise nil end - def initialize(name, options) + # Default url options which can be used as prefix. + def self.default_url_options + {} + end + + def initialize(name, options) #:nodoc: options.assert_valid_keys(:class_name, :as, :path_names, :singular, :path_prefix) @as = (options[:as] || name).to_sym @@ -79,10 +84,12 @@ module Devise # you should overwrite this method to use it. The only information supported # by default is I18n.locale. # - # TODO This is a hack. Setting default_url_options that are shared by - # controllers and devise seems to be the best solution. def parsed_path - raw_path.gsub(":locale", I18n.locale.to_s) + returning raw_path do |path| + self.class.default_url_options.each do |key, value| + path.gsub!(key.inspect, value.to_s) + end + end end # Create magic predicates for verifying what module is activated by this map. diff --git a/lib/devise/rails/routes.rb b/lib/devise/rails/routes.rb index 50671c19..969b6616 100644 --- a/lib/devise/rails/routes.rb +++ b/lib/devise/rails/routes.rb @@ -60,11 +60,16 @@ module ActionController::Routing # # map.devise_for :users, :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' } # - # * :path_prefix => the path prefix to be used in all routes. Only :locale is supported as dynamic prefix: + # * :path_prefix => the path prefix to be used in all routes. # # map.devise_for :users, :path_prefix => "/:locale" # - # When setting a dynamic path prefix, be sure to set default_url_options with the locale on your ApplicationController as well. + # If you are using a dynamic prefix, like :locale above, you need to configure default_url_options through Devise. You can do that in config/initializers/devise.rb or setting a Devise.default_url_options: + # + # Devise.default_url_options do + # { :locale => I18n.locale } + # end + # def devise_for(*resources) options = resources.extract_options! @@ -98,7 +103,7 @@ module ActionController::Routing def confirmable(routes, mapping) routes.resource :confirmation, :only => [:new, :create, :show], :as => mapping.path_names[:confirmation] end - end + end end end diff --git a/test/controllers/filters_test.rb b/test/controllers/filters_test.rb index aff45bb6..0674da3d 100644 --- a/test/controllers/filters_test.rb +++ b/test/controllers/filters_test.rb @@ -91,4 +91,13 @@ class ControllerAuthenticableTest < ActionController::TestCase test 'is not a devise controller' do assert_not @controller.devise_controller? end + + test 'default url options are retrieved from devise' do + begin + Devise.default_url_options {{ :locale => I18n.locale }} + assert_equal({ :locale => :en }, @controller.send(:default_url_options)) + ensure + Devise.default_url_options {{ }} + end + end end diff --git a/test/mapping_test.rb b/test/mapping_test.rb index d45d7c3f..45cebea9 100644 --- a/test/mapping_test.rb +++ b/test/mapping_test.rb @@ -76,8 +76,13 @@ class MappingTest < ActiveSupport::TestCase end test 'parsed path is returned' do - assert_equal '/account', Devise.mappings[:account].parsed_path - assert_equal '/en/organizers', Devise.mappings[:manager].parsed_path + begin + Devise.default_url_options {{ :locale => I18n.locale }} + assert_equal '/account', Devise.mappings[:account].parsed_path + assert_equal '/en/organizers', Devise.mappings[:manager].parsed_path + ensure + Devise.default_url_options {{ }} + end end test 'magic predicates' do