Rails Can't find route in Functional Test - ruby-on-rails

Rails version 3.0.4 and Ruby 1.9.2
I'm using the devise gem, and have my application set up so that a user must sign in to perform any action. While writing my functional tests, I found that all of the test threw the same error.
`method_missing': undefined method `new_user_session_path'
This is strange as, if I rake routes I can see
new_user_session GET /devise/login(.:format) {:action=>"new", :controller=>"devise/sessions"}
I can also confirm that when I run the application, all of the link_tos work, when using that path.
Is there something special I have to do for a certain controller's test to see other routes?
routes.rb
Nge::Application.routes.draw do
resources :companies
resources :users
devise_for :users, :path => "devise", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
...
end
test/functional/companies_controller_test.rb
require 'test_helper'
class CompaniesControllerTest < ActionController::TestCase
context "When a user is NOT signed in" do
[:index, :new].each do |action|
context "and GET ##{action.to_s}" do
setup {get action}
should set_the_flash.to(/must sign-up/)
should redirect_to(new_user_session_path)
end
end
...
end
end

You need to add
#request.env["devise.mapping"] = Devise.mappings[:user]
somewhere in your test, probably in the setup method.
See discussion here.

Can you try re-ordering the routes so that the devise routes are first?
So the routes.rb file would look something like this -
Nge::Application.routes.draw do
resources :companies
devise_for :users, :path => "devise", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
resources :users
...
end

Related

Rails 4 Devise custom routes

I am using 'devise', '~> 3.4.1' and rails 4 in my app. When I try to create custom routes am getting wiered error. What else I need to add in my route.rb
Error:
ArgumentError: ' devise/sessions' is not a supported controller name.
This can lead to potential routing problems.
See
routes.rb
Rails.application.routes.draw do
devise_for :users
devise_scope :user do
get 'register', to: 'devise/registrations#new', as: :register
get 'login', to: ' devise/sessions#new', as: :login
end
The problem occured at login route.
There is a typo in your code, a space before 'devise/sessions#new'.
This,
get 'login', to: ' devise/sessions#new', as: :login
should be
get 'login', to: 'devise/sessions#new', as: :login
Try out this code:
devise_scope :user do
get '/login' => 'devise/sessions#new'
get '/register' => 'devise/registrations#new'
end
You need to do it this
devise_for :users, path_names: {
sign_in: 'login', sign_out: 'logout',
password: 'secret', confirmation: 'verification',
registration: 'register', edit: 'edit/profile'
}
Source:
http://www.rubydoc.info/github/plataformatec/devise/ActionDispatch/Routing/Mapper:devise_for
devise_for :user, :path => ' ', :path_names => { :sign_in => "login" :sign_up => "register" }

Devise custom routing links not working

I am running Rails 3.2.12 and Devise 3.1 and I have in the routes.rb this:
devise_for :users do
get '/login' => 'devise/sessions#new', as: :login
get '/logout' => 'devise/sessions#destroy', as: :logout
end
However, when I hit
127.0.0.1:3000/login
I get
No route matches [GET] "/login"
What works is
127.0.0.1:3000/users/login
Is there anything else I have to do so that I can skip typing /users/ part?
Thank you!
devise_for :users, :path => '', :path_names => { :sign_in => 'login'}
Good info about customizing Devise paths on this StackOverflow post :)
Here's some live code which works for one of our live apps:
#User Management (Devise)
devise_for :users, :path => '', :controllers => {:sessions => 'sessions', :registrations => 'registrations'}, :path_names => { :sign_in => 'login', :password => 'forgot', :confirmation => 'confirm', :unlock => 'unblock', :registration => 'register', :sign_up => 'new', :sign_out => 'logout'}
as :user do
get 'register', :to => 'devise/registrations#new'
delete 'logout', :to => 'sessions#destroy'
end
devise_scope :user do
get "/login" => "devise/sessions#new"
end
See this for more details

Is it possible to have different paths on the same devise model with constraints?

I'm trying to have different paths for the same devise model/resource with constraints, but the first path is the one being applied in this case "visitor".
constraints(ValidSubdomainFrontend) do
devise_for :users, :path => "visitor", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
end
constraints(ValidSubdomainAdmin) do
devise_for :users do
get 'users', :path => "admin", :to => 'site_backend#index', :as => :user_root # Rails 3
end
devise_for :users, :controllers => { :registrations => 'users' }, :path => "admin", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
end
Is it possible to have different paths for the same resource with Devise on different constraints?
The constraints being used are:
class ValidSubdomainAdmin
def self.matches?(request)
request.subdomain.present? &&
request.env['PATH_INFO'].start_with?('/admin')
end
end
class ValidSubdomainFrontend
def self.matches?(request)
request.subdomain.present? &&
!request.env['PATH_INFO'].start_with?('/admin')
end
end
Is this possible with Devise at all or is this a Bug?
Found the solution for this issue!
More on the context, basically needed to have something like /visitor on the front-end where users can login (to the members area) and edit their profile and other members/clients operations. But I would also want /admin where admins/editors/authors can login to the (backend) admin dashboard/area. Both areas use the same Devise model/resource (so an admin can also visit the members area). As a side note, currently I'm using CanCan permissions to prevent members from accessing the admin area.
I just had to replace the admin area constraint for:
constraints(ValidSubdomainAdmin) do
devise_scope :user do
#root :to => "devise/registrations#new"
get "admin/" => "admin#index"
post 'admin/' => 'devise/registrations#new', :as => :new_admin_registration
match 'admin/', :to => 'admin#index'
get "admin/edit" => "devise/registrations#edit"
match 'admin/edit', :to => 'devise/registrations#edit'
get "admin/login" => "devise/sessions#new", :as => :new_admin_session
match 'admin/login', :to => 'devise/sessions#new'
get "admin/logout" => "devise/sessions#destroy", :as => 'destroy_admin_session'
match 'admin/logout', :to => 'devise/sessions#destroy'
post "admin/password" => "devise/passwords#create"
get "admin/password/new" => "devise/passwords#new", :as => 'new_admin_password'
get "admin/password/edit" => "devise/passwords#edit"
put "admin/password" => "devise/passwords#update"
end
end
I also updated the views /admin/users (being used by devise on the on the admin area) to use the new admin devise paths.
Many thanks to José Valim

Changing the sign_in url for Devise

How do you change the sign in path for Devise when using a before_filter :athenticate user?
I have the following in a Posts controller.
eg:
class PostsController < ApplicationController
before_filter :authenticate_user!
def index
#posts = Post.all
end
end
At the moment it automatically goes to '/users/sign_in'
I'd like to use '/login'
Sorted for now folks, using the devise_for method.
devise_for :users, :controllers => { :registrations => 'registrations' }, :path => 'accounts', :path_names => { :sign_in => 'login', :sign_up => 'new', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification' }
So now the sign_in path is 'accounts/login'
That solution doesn't modify the resource path for sign_in.
I did however sort it out via the devise_for method. eg:
devise_for :users,
:controllers => { :registrations => 'registrations' },
:path => 'accounts',
:path_names => { :sign_in => 'login',
:sign_up => 'new',
:sign_out => 'logout',
:password => 'secret',
:confirmation => 'verification' }
So now the sign_in path is 'accounts/login'
I think the info you are looking for is here: https://github.com/plataformatec/devise/wiki/How-To:-Change-the-default-sign_in-and-sign_out-routes
Stolen from the docs:
devise_scope :user do
get "/login" => "devise/sessions#new"
end
In you case you would use :post instead of :user I believe.
Its late and I am fuzzy headed but I think that should do it.

Remove model from Devise urls

How do I remove the model name from Devise urls?
Ie
users/sign_in -> /sign_in
users/sign_out -> /sign_out
users/registration/sign_up -> /sign_up
users/registration/edit -> /edit
This is covered in the devise README (https://github.com/plataformatec/devise):
Devise also ships with default routes.
If you need to customize them, you
should probably be able to do it
through the devise_for method. It
accepts several options like
:class_name, :path_prefix and so on,
including the possibility to change
path names for I18n:
devise_for :users, :path => "usuarios", :path_names => { :sign_in => 'login', :sign_out => 'logout', :password => 'secret', :confirmation => 'verification', :unlock => 'unblock', :registration => 'register', :sign_up => 'cmon_let_me_in' }
Be sure to check
devise_for documentation for details.
If you have the need for more deep
customization, for instance to also
allow "/sign_in" besides
"/users/sign_in", all you need to do
is to create your routes normally and
wrap them in a devise_scope block in
the router:
devise_scope :user do
get "sign_in", :to => "devise/sessions#new"
end
This way
you tell devise to use the scope :user
when "/sign_in" is accessed. Notice
devise_scope is also aliased as as and
you can also give a block to
devise_for, resulting in the same
behavior:
devise_for :users do
get "sign_in", :to => "devise/sessions#new"
end
Feel free
to choose the one you prefer!
(Maybe this wasn't in the README when this question was originally posed.)
The way to do this manually is Rails 3 would be:
match 'sign_in' => 'devise/sessions#new', :as => :sign_in
match 'sign_out' => 'devise/sessions#destroy', :as => :sign_out

Resources