lib/devise/rails/routes.rb in devise-1.1.rc2 vs lib/devise/rails/routes.rb in devise-1.1.0
- old
+ new
@@ -13,35 +13,38 @@
class Mapper
# Includes devise_for method for routes. This method is responsible to
# generate all needed routes for devise, based on what modules you have
# defined in your model.
#
- # Examples: Let's say you have an User model configured to use
- # authenticatable, confirmable and recoverable modules. After creating this
- # inside your routes:
+ # ==== Examples
#
+ # Let's say you have an User model configured to use authenticatable,
+ # confirmable and recoverable modules. After creating this inside your routes:
+ #
# devise_for :users
#
# This method is going to look inside your User model and create the
# needed routes:
#
# # Session routes for Authenticatable (default)
- # new_user_session GET /users/sign_in {:controller=>"sessions", :action=>"new"}
- # user_session POST /users/sign_in {:controller=>"sessions", :action=>"create"}
- # destroy_user_session GET /users/sign_out {:controller=>"sessions", :action=>"destroy"}
+ # new_user_session GET /users/sign_in {:controller=>"devise/sessions", :action=>"new"}
+ # user_session POST /users/sign_in {:controller=>"devise/sessions", :action=>"create"}
+ # destroy_user_session GET /users/sign_out {:controller=>"devise/sessions", :action=>"destroy"}
#
# # Password routes for Recoverable, if User model has :recoverable configured
- # new_user_password GET /users/password/new(.:format) {:controller=>"passwords", :action=>"new"}
- # edit_user_password GET /users/password/edit(.:format) {:controller=>"passwords", :action=>"edit"}
- # user_password PUT /users/password(.:format) {:controller=>"passwords", :action=>"update"}
- # POST /users/password(.:format) {:controller=>"passwords", :action=>"create"}
+ # new_user_password GET /users/password/new(.:format) {:controller=>"devise/passwords", :action=>"new"}
+ # edit_user_password GET /users/password/edit(.:format) {:controller=>"devise/passwords", :action=>"edit"}
+ # user_password PUT /users/password(.:format) {:controller=>"devise/passwords", :action=>"update"}
+ # POST /users/password(.:format) {:controller=>"devise/passwords", :action=>"create"}
#
# # Confirmation routes for Confirmable, if User model has :confirmable configured
- # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"confirmations", :action=>"new"}
- # user_confirmation GET /users/confirmation(.:format) {:controller=>"confirmations", :action=>"show"}
- # POST /users/confirmation(.:format) {:controller=>"confirmations", :action=>"create"}
+ # new_user_confirmation GET /users/confirmation/new(.:format) {:controller=>"devise/confirmations", :action=>"new"}
+ # user_confirmation GET /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"show"}
+ # POST /users/confirmation(.:format) {:controller=>"devise/confirmations", :action=>"create"}
#
+ # ==== Options
+ #
# You can configure your routes with some options:
#
# * :class_name => setup a different class to be looked up by devise,
# if it cannot be correctly find by the route name.
#
@@ -60,100 +63,184 @@
# * :path_names => configure different path names to overwrite defaults :sign_in, :sign_out, :sign_up,
# :password, :confirmation, :unlock.
#
# 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.
+ # * :controllers => the controller which should be used. All routes by default points to Devise controllers.
+ # However, if you want them to point to custom controller, you should do:
#
- # devise_for :users, :path_prefix => "/:locale"
+ # devise_for :users, :controllers => { :sessions => "users/sessions" }
#
- # If you are using a dynamic prefix, like :locale above, you need to configure default_url_options in your ApplicationController
- # class level, so Devise can pick it:
+ # * :module => the namespace to find controlers. By default, devise will access devise/sessions,
+ # devise/registrations and so on. If you want to namespace all at once, use module:
#
- # class ApplicationController < ActionController::Base
- # def self.default_url_options
- # { :locale => I18n.locale }
- # end
- # end
+ # devise_for :users, :module => "users"
#
- # * :controllers => the controller which should be used. All routes by default points to Devise controllers.
- # However, if you want them to point to custom controller, you should do:
+ # Notice that whenever you use namespace in the router DSL, it automatically sets the module.
+ # So the following setup:
#
- # devise_for :users, :controllers => { :sessions => "users/sessions" }
+ # namespace :publisher
+ # devise_for :account
+ # end
#
+ # Will use publisher/sessions controller instead of devise/sessions controller. You can revert
+ # this by providing the :module option to devise_for.
+ #
# * :skip => tell which controller you want to skip routes from being created:
#
# devise_for :users, :skip => :sessions
#
+ # ==== Scoping
+ #
+ # Following Rails 3 routes DSL, you can nest devise_for calls inside a scope:
+ #
+ # scope "/my" do
+ # devise_for :users
+ # end
+ #
+ # However, since Devise uses the request path to retrieve the current user, it has one caveats.
+ # If you are using a dynamic segment, as below:
+ #
+ # scope ":locale" do
+ # devise_for :users
+ # end
+ #
+ # You are required to configure default_url_options in your ApplicationController class level, so
+ # Devise can pick it:
+ #
+ # class ApplicationController < ActionController::Base
+ # def self.default_url_options
+ # { :locale => I18n.locale }
+ # end
+ # end
+ #
def devise_for(*resources)
options = resources.extract_options!
+
+ if as = options.delete(:as)
+ ActiveSupport::Deprecation.warn ":as is deprecated, please use :path instead."
+ options[:path] ||= as
+ end
+
+ if scope = options.delete(:scope)
+ ActiveSupport::Deprecation.warn ":scope is deprecated, please use :singular instead."
+ options[:singular] ||= scope
+ end
+
+ options[:as] ||= @scope[:as] if @scope[:as].present?
+ options[:module] ||= @scope[:module] if @scope[:module].present?
+ options[:path_prefix] ||= @scope[:path] if @scope[:path].present?
+ options[:path_names] = (@scope[:path_names] || {}).merge(options[:path_names] || {})
+
resources.map!(&:to_sym)
resources.each do |resource|
- mapping = Devise.add_model(resource, options)
+ mapping = Devise.add_mapping(resource, options)
begin
raise_no_devise_method_error!(mapping.class_name) unless mapping.to.respond_to?(:devise)
+ rescue NameError => e
+ raise unless mapping.class_name == resource.to_s.classify
+ warn "[WARNING] You provided devise_for #{resource.inspect} but there is " <<
+ "no model #{mapping.class_name} defined in your application"
+ next
rescue NoMethodError => e
raise unless e.message.include?("undefined method `devise'")
raise_no_devise_method_error!(mapping.class_name)
end
routes = mapping.routes
routes -= Array(options.delete(:skip)).map { |s| s.to_s.singularize.to_sym }
- routes.each do |mod|
- send(:"devise_#{mod}", mapping, mapping.controllers)
+ devise_scope mapping.name do
+ yield if block_given?
+ with_devise_exclusive_scope mapping.fullpath, mapping.name do
+ routes.each { |mod| send(:"devise_#{mod}", mapping, mapping.controllers) }
+ end
end
end
end
+ # Allow you to add authentication request from the router:
+ #
+ # authenticate(:user) do
+ # resources :post
+ # end
+ #
def authenticate(scope)
constraint = lambda do |request|
request.env["warden"].authenticate!(:scope => scope)
end
constraints(constraint) do
yield
end
end
+ # Sets the devise scope to be used in the controller. If you have custom routes,
+ # you are required to call this method (also aliased as :as) in order to specify
+ # to which controller it is targetted.
+ #
+ # as :user do
+ # get "sign_in", :to => "devise/sessions#new"
+ # end
+ #
+ # Notice you cannot have two scopes mapping to the same URL. And remember, if
+ # you try to access a devise controller without specifying a scope, it will
+ # raise ActionNotFound error.
+ def devise_scope(scope)
+ constraint = lambda do |request|
+ request.env["devise.mapping"] = Devise.mappings[scope]
+ true
+ end
+
+ constraints(constraint) do
+ yield
+ end
+ end
+ alias :as :devise_scope
+
protected
- def devise_session(mapping, controllers)
- scope mapping.full_path do
- get mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#new", :as => :"new_#{mapping.name}_session"
- post mapping.path_names[:sign_in], :to => "#{controllers[:sessions]}#create", :as => :"#{mapping.name}_session"
- get mapping.path_names[:sign_out], :to => "#{controllers[:sessions]}#destroy", :as => :"destroy_#{mapping.name}_session"
+ def devise_session(mapping, controllers) #:nodoc:
+ scope :controller => controllers[:sessions], :as => :session do
+ get :new, :path => mapping.path_names[:sign_in]
+ post :create, :path => mapping.path_names[:sign_in], :as => ""
+ get :destroy, :path => mapping.path_names[:sign_out]
end
end
- def devise_password(mapping, controllers)
- scope mapping.full_path, :name_prefix => mapping.name do
- resource :password, :only => [:new, :create, :edit, :update], :path => mapping.path_names[:password], :controller => controllers[:passwords]
- end
+ def devise_password(mapping, controllers) #:nodoc:
+ resource :password, :only => [:new, :create, :edit, :update],
+ :path => mapping.path_names[:password], :controller => controllers[:passwords]
end
- def devise_confirmation(mapping, controllers)
- scope mapping.full_path, :name_prefix => mapping.name do
- resource :confirmation, :only => [:new, :create, :show], :path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
- end
+ def devise_confirmation(mapping, controllers) #:nodoc:
+ resource :confirmation, :only => [:new, :create, :show],
+ :path => mapping.path_names[:confirmation], :controller => controllers[:confirmations]
end
- def devise_unlock(mapping, controllers)
- scope mapping.full_path, :name_prefix => mapping.name do
- resource :unlock, :only => [:new, :create, :show], :path => mapping.path_names[:unlock], :controller => controllers[:unlocks]
+ def devise_unlock(mapping, controllers) #:nodoc:
+ if mapping.to.unlock_strategy_enabled?(:email)
+ resource :unlock, :only => [:new, :create, :show],
+ :path => mapping.path_names[:unlock], :controller => controllers[:unlocks]
end
end
- def devise_registration(mapping, controllers)
- scope mapping.full_path[1..-1], :name_prefix => mapping.name do
- resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
- :path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
- end
+ def devise_registration(mapping, controllers) #:nodoc:
+ resource :registration, :only => [:new, :create, :edit, :update, :destroy], :path => mapping.path_names[:registration],
+ :path_names => { :new => mapping.path_names[:sign_up] }, :controller => controllers[:registrations]
end
- def raise_no_devise_method_error!(klass)
+ def with_devise_exclusive_scope(new_path, new_as) #:nodoc:
+ old_as, old_path, old_module = @scope[:as], @scope[:path], @scope[:module]
+ @scope[:as], @scope[:path], @scope[:module] = new_as, new_path, nil
+ yield
+ ensure
+ @scope[:as], @scope[:path], @scope[:module] = old_as, old_path, old_module
+ end
+
+ def raise_no_devise_method_error!(klass) #:nodoc:
raise "#{klass} does not respond to 'devise' method. This usually means you haven't " <<
"loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' " <<
"inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb'"
end
end