I recently turned to devise for my authentication routine. However, i'm still having some problems with it and mainly with routing. After a user logs in, i have the routes :
devise_for :users
namespace :user do
root :to => "town#index"
end
After i log in, i'm redirected to town controller. There i have this line :
<%= link_to raw("<p class='menu_head'>#{t('menu.inventory')}</p>"), :controller => "character" %>
This actually worked well with restful authentication, but for devise to work i have to specify the controller as "/character", else i get a :
No route matches {:controller=>"user/character"}
Though this route is incorrect. How can this be fixed ?
Moreover, i think this one is caused by devise once more. When a new user signs up, devise redirects them to town#index as it would happen if they have logged in. When this happens, for some reason current_user is not initialized. This only happens after sign up not when a user logs in. I'm pretty sure that i'm doing something wrong with devise.
You should be using the routing helpers rather than the options to get to this controller. Define a path helper in your routes file and use that instead. This way, you'll always be given the right URL.
At the moment, your application is sending you to users/town because that's what you're telling it to. The URL for sign in is /users/sign_in and by passing :controller you're saying "go to /users/town. If you were using named routes this would not occur.
Related
In the answer to this question about routes in Devise: Devise & Custom Rails User URLs
There is a line of code:
match '/:user' => "users#show", :as => :user_profile
That apparently works for the question asker, but not for me. I end up with
NoMethodError in UsersController#show
undefined method `books' for nil:NilClass
when I go to localhost:3000/username instead of localhost:3000/user/username. I assume because the match line above isn't working correctly and that url does not refer to any user, according to my routes file.
The second url routes me to the user's show page, but I don't want the extra /user in the url.
So I'm trying to figure out exactly what '/:user', :as, and :user_profile mean because I think I'm supposed to substitute a few things here specific to my app. I think :as is some kind of aliased method. I can't find anything in the Devise documentation about a route called user_profile. And I don't know what '/:user' is referring to. An instance of the User object? A user attribute/unique column in my database that I use to refer to specific users? (I use permalink for my user-defined urls).
The route is working for you. Thats why ur getting error from users_controller#show.
In your show action you must be doing something like User.where(:id => params[:id]). But in this case, the attribute in your params is called :user . So to make make both routes work, without any change in the show action, change the route to
match '/:id' => "users#show", :as => :user_profile
Devise documentation won't refer to a 'user_profile' because it is a custom route being used to help address the issue that the questioner (in the linked question) was asking.
match '/:user' => "users#show" means "match any route with a single parameter after / that doesn't match a previously defined route, pair this route to the UsersController 'show' action (passing along the singe parameter as 'user')"
Modifying a route using :as => :anything will provide several helper methods to refer to this route that may be used in controllers, views, and mailers (in this case anything_path and anything_url).
As far as why this won't work for you, this is likely do to a problem with this entry in regard to the rest of your routes or because of your controller action itself. Posting these can help someone track down the exact reason...
I'm attempting to install Devise on a rather simple event creating/displaying Rails 4 app. I have 2 static pages and the index page displaying without authentication, and all is well there. Anything else kicks you to the "sign up" page. From there, when I attempt to create an account for myself (to simply see the other pages- simple vanilla devise installation attempt) I get a "No route matches [POST] "/registrations/user" error when clicking "submit" (f.submit)
I am using Rails 4, have the 3.0.3 version of Devise, bundled it, ran "rails generate devise:install" to install it, ran "rails generate devise user", ran db:migrate, raked the routes, and restarted the Rails server.
I even recreated the button action with the "correct" route and "get post" - no dice.
Anybody have any idea? I'm at a loss here.
Well it's always tricking debugging sever-side code without seeing it in action, but here's what should work.
yourappname/config/routes.rb :
devise_scope :user do
# matches the url '/register' to the registration controller's 'new' action and creates a :register symbol inorder to reference the link dynamically in the rest of the code
get 'register', to: 'devise/registrations#new', as: :register
end
(Assuming your register button is in your app's partial)
yourappname/app/views/layouts/application.html.erb:
<%= link_to "Register", register_path, class: "btn" %>
Now you could actually put that link_to anywhere, in any page, and it'll work. The reason for this is the 'register_path'.
When you create your route, the as: :register parameter creates a global variable that can be accessed throughout your app.
the register_path variable in your link_to method will always call the right action, even if you change your routes file.
It's just syntax. You could create any symbol you want. This would also work:
routes.rb:
# Inside get method, third parameter
as: :bowtiesarecool
someview.html.erb:
# Inside link_to method, second parameter
bowtiesarecool_path
Just match the variable name with the symbol name and a put a _path after it. The link_to method will handle everything else!
right now in my app users can sign in at /users/sign_in . But I would rather have them sign in and sign up at a same place so i have a view already created at /home/all. That being said, how do I make sure that every time users go to /users/sign_in or /users/sign_up they are redirect to /home/all ?
Thanks
You can do this by overriding the devise's default route,
get "/users/sign_up" => 'home#all'
get "/users/sign_in" => 'home#all'
write this to lines in routes file before, devise_for :users.
Whenever request comes from /users/sign_up/ or /users/sign_in/, it will be handled by home#all
I am using Rails 3 and devise and am trying to make it so that when a person comes to my web app, they are taken directly to the user registration sign_up link instead of the sign in link.
I'm pretty sure that I'm having this problem because my routes are configured like:
root :to => "babies#new"
Accessing the baby model requires a user to be logged in. To get around this I've tried changing this to:
root :to => "users#sign_up"
It doesn't seem to work? I get an error saying that I have an:
uninitialized constant UsersController
Can anyone suggest what I'm doing wrong?
Thanks in advance!
One of the solutions is to create separate controller say main and an action in it sign_up_redirect. Then configure your routes file like this:
root :to => "main#sign_up_redirect"
and write in that action next:
redirect_to new_user_registration_path
* path to registration can be different to you
The following error happens when the corresponding controller is not found. You should check whether you are having UsersController or UserController
uninitialized constant UsersController
Unless you are scoping the Devise routes, root :to => 'users#sign_up' doesn't exist. I would also highly recommend against setting any Devise route as your root as all of the Devise hooks redirect to root ie. after_sign_up, after_sign_in, after_update. I think that for the desired outcome you have two options.
First would be to simply put a sign up form on the page at your root url. You can follow the logic in this tutorial to accomplish this, obviously changing from sign in to sign up.
The second option that comes readily to mind is to create a passthrough controller that simply has an index action that redirects to the sign up page. Something like that could look like this.
class PassthroughController < ApplicationController
def index
redirect_to 'devise/registrations#new'
end
end
Either option is simple enough to implement.
I am working on a rails application and added a simple login system according to a book.
I created the controller admin:
rails generate controller admin login logout index
It added the following routes to routes.db
get "admin/login"
get "admin/logout"
get "admin/index"
I can got to http://localhost:3000/admin/login there is no problem at all.
But when I try to login I get: No route matches "/admin/login"!
Now, the first confusing part is that the "login" method of my AdminController is not executed at all.
The second confusing part is that this code works like a charm - redirects everything to /admin/login:
def authorize
unless User.find_by_id(session[:user_id])
flash[:notice] = "you need to login"
redirect_to :controller => 'admin', :action => 'login'
end
end
Sidenotes:
I restarted the server several times.
I tried a different browser - to be sure there is no caching problem.
Try
match "/admin/login" => "admin#login"
match "/admin/logout" => "admin#logout"
match "/admin/index" => "admin#index"
(notice the leading /)
As an aside, unless you're creating a login system to learn about Rails and/or authentication, you're probably better off using something like Devise.
Following on from David Sulc's answer:
You're defining the routes as get requests, meaning to go to them you must perform a GET /admin/login request which is basically what happens when you type the URL into your address bar or follow a link that uses it.
However when you try to use these URLs in a form, the form does a POST request and because you've defined all of these as get-only requests, Rails will not be able to find a compatible route.
I definitely agree with David that you should look at an alternative system such as Devise.