Class: ActionDispatch::Routing::Mapper

Inherits:
Object
  • Object
show all
Defined in:
lib/devise/rails/routes.rb

Instance Method Summary collapse

Instance Method Details

#authenticate(scope) ⇒ Object

Allow you to add authentication request from the router:

authenticate(:user) do
  resources :post
end


169
170
171
172
173
174
175
176
177
# File 'lib/devise/rails/routes.rb', line 169

def authenticate(scope)
  constraint = lambda do |request|
    request.env["warden"].authenticate!(:scope => scope)
  end

  constraints(constraint) do
    yield
  end
end

#devise_for(*resources) ⇒ Object

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:

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=>"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=>"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=>"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.

    devise_for :users, :class_name => 'Account'

* :path => allows you to setup path name that will be used, as rails routes does.
           The following route configuration would setup your route as /accounts instead of /users:

    devise_for :users, :path => 'accounts'

* :singular => setup the singular name for the given resource. This is used as the instance variable name in
               controller, as the name in routes and the scope given to warden.

    devise_for :users, :singular => :user

* :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' }

* :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, :controllers => { :sessions => "users/sessions" }

* :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:

    devise_for :users, :module => "users"

  Notice that whenever you use namespace in the router DSL, it automatically sets the module.
  So the following setup:

    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


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/devise/rails/routes.rb', line 116

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_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 }

    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

#devise_scope(scope) ⇒ Object Also known as: as

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.



190
191
192
193
194
195
196
197
198
199
# File 'lib/devise/rails/routes.rb', line 190

def devise_scope(scope)
  constraint = lambda do |request|
    request.env["devise.mapping"] = Devise.mappings[scope]
    true
  end

  constraints(constraint) do
    yield
  end
end