I am attempting to manage users in my app that uses Devise for the authentication. I followed the steps here in order to create a UsersController to allow me to do so. However, when I attempt to sign out, it says that the path /d/users/sign_out cannot be found. Is there anything else I need to add to get this to work?
EDIT: My routes look like:
devise_for :users. :path_prefix => 'd'
resources :users do
# stuff here
end
When I run rake routes, it gives me, for the destroy_user_session_path:
destroy_user_session DELETE /d/users/sign_out(.:format) {:controller=>"devise/sessions", :action=>"destroy"}
When I remove the path_prefix part, it attempts to 'show' a user with the ID sign_out
link_to "sign_out", destroy_user_session_path, method: :delete
do you have the method :delete in your view?
Related
I have been working my way through the Railscasts videos and trying to adapt them for the latest
version of rails, being version 6. I am up to the following episode:
http://railscasts.com/episodes/124-beta-invitations
The video explains that you need to have some form of authorisation/authentication in place prior to the changes,
so I followed the instructions on the following site to do so:
https://www.nopio.com/blog/authentication-authorization-rails/
I stopped at Step 20 as the final step was not needed. Here devise is the main gem used for most
of the heavy lifting.
Now as far as the railscast goes I am at the point where we need to alter the signup path, which is where I am stuck, and the example given, of a change to routes file, is as follows:
map.signup '/signup/:invitation_token', :controller => 'users', :action => 'new'
There is also a comment from some time after going down the same path as me and using devise
which shows the following:
devise_for :users, :controllers => {:registrations => 'registrations'} do
get 'users/sign_up/:invitation_token' => 'devise/registrations#new', :as => "new_user_registration"
end
After entering the above and running rails routes, I cannot find any changes to the entry, ie. the addition of the :invitation_token and the sign_up path still looks as follows:
new_user_registration GET /users/sign_up(.:format) registrations#new
My understanding is it should look like:
new_user_registration GET /users/sign_up/:invitation_token(.:format) registrations#new
If someone could point in the right direction, it would be greatly appreciated :)
Please let me know if any additional information is required to assist in a solution?
as far as I'm aware devise doesn't let you modify the default registration path using devise_for (see the method docs: https://www.rubydoc.info/github/plataformatec/devise/master/ActionDispatch/Routing/Mapper%3adevise_for)
what you can do instead is use the devise_scope.
devise_scope :user do
post 'users/sign_up/:invitation_token', to: 'registrations#new', as: 'new_user_registration'
end
note that because you are using your own registrations controller you need to point the new path to use this controller, not the devise one.
After customising Devise routes, I have some issues with the routing.
Currently setup (but failing):
/me/account loads Devise::Registration#edit form
/me/account/:what routes to account_controller#edit
My routes (shortcut):
devise_for :users do
...
end
devise_scope :user do
scope "/me/account" do
get "/" => "users/registrations#edit", :as => :my_account
get "/:what" => "accounts#edit", :as => :my_account_edit
end
end
resources :accounts, :only => [:edit, :update]
Rake routes output:
activate_account GET /reactivate(.:format) users#reactivate
my_account GET /me/account(.:format) users/registrations#edit
my_account_edit GET /me/account/:what(.:format) accounts#edit
cancel GET /me/account/cancel(.:format) users/registrations#cancel
DELETE /me/account(.:format) users/registrations#destroy
edit_account GET /accounts/:id/edit(.:format) accounts#edit
account PATCH /accounts/:id(.:format) accounts#update
PUT /accounts/:id(.:format) accounts#update
Account
Since /me/account is actually showing registrations#edit ( Devise ) and all the /me/account/helpme are custom form fields
This has issues:
No notices shown on /me/account on update or failure
On failure the form is not repopulated with earlier filled in form values
Its not updating the form
/me/account/helpme goes , on form submit , to /accounts/1 ( the current user id ) and throws error
No route matches {:action=>"edit", :controller=>"accounts", :id=>"1", :what=>nil} missing required keys: [:what]
These issues are totally driving me insane. Anyone can provide me some suggestions to fix (one or more ) of these routing issues?
About form submit error.
You need to override url in your form to submit to:
<%= form_for #resource, url: my_account_edit(what: params[:what]) do |f| %>
This should be done in your views or in devise-generated views.
If you didn't generated devise views, then, just run in terminal:
rails g devise:views
EDIT
And you should tell us how your form in views looks like, and how controller handles updates of custom fields.
I am trying to replace user profile views of the sort
/users/1
with
/username
I'm aware this means I'll need to check for collisions of various kinds. I've consulted the following similar SO questions:
Ruby on rails routing matching username
customize rails url with username
Routing in Rails making the Username an URL:
routing error with :username in url
Here are the various failed routes.rb route definitions I've tried, and associated errors:
match "/:username" => "users#show", via: "get"
Here's the error:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User without an ID
app/controllers/users_controller.rb:7:in `show'
Here is my corresponding users_controller:
6 def show
7 #user = User.find(params[:id])
8 end
match "/:username" => 'users#show', :as => :profile
Same error as above.
match "/:username", :controller => "users/:id", :action => 'show'
Routing Error
uninitialized constant Users
Try running rake routes for more information on available routes.
match '/:username', :controller => 'users', :action => 'show'
Same error as 1.
match '/:username', to: 'users/:id', via: 'show'
Server does not start.
match "/:username" => redirect("/users/:id")
Error:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with id=:id
Any idea why my routing is not working the same way that everyone else who asks this question's is?
Update
Just to take this issue out of the comments and put it in the question more cleanly. After making the change by #Ryan Bigg below, I had a routing problem in my redirect to profile when a new one is created. Here's my create code:
def create
#user = User.new(params[:user])
if #user.save
session[:user_id] = #user.id
flash[:success] = "Thank you for signing up."
redirect_to ('/'+#user.username)
#redirect_to #user, notice: "Thank you for signing up!"
else
render "new"
end
end
And here is my user.rb
def to_param
self.username
#username
end
However, the commented out redirect, which I think should work with the to_param update, doesn't work, while the ugly hackish one above it does. Why is the to_param overwrite, which worked for other people, not working on my app? My #update and #edit methods are also not working, as their redirects go to "users/1/edit" instead of "username/edit" if overwriting to_param doesn't take care of this.
The first one is correct, but isn't working because you're still attempting to do something like this inside your controller:
User.find(params[:username])
When you should instead be doing this:
User.find_by_username!(params[:username])
The first one will attempt to find by the primary key of your table, where the second one will, correctly, query on the username field instead.
In addition to the update for to_params, the bottom of the routes file needs the following line:
resources :users, :path => '/'
I am using Devise in my site I create admin namespace and giving functionality of create user by admin.
my routes are as under
devise_for :users,:has_many => :comments, :controllers => {:sessions =>'devise/sessions',:registrations => 'devise/registrations'} do
get "/login", :to => "devise/sessions#new", :as => :login
get "/signup", :to => "devise/registrations#new", :as => :signup
get "/logout", :to => "devise/sessions#destroy", :as => :logout
end
when i click on add_user link which has signup_path causing following error:
My Error
Started GET "/signup" for 127.0.0.1 at Fri Mar 09 12:49:11 +0530 2012
Processing by Devise::RegistrationsController#new as HTML
User Load (0.1ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 35 LIMIT 1
Redirected to http://localhost:3000/admin
Filter chain halted as :require_no_authentication rendered or redirected
Completed 302 Found in 3ms (ActiveRecord: 0.1ms)
I think it going to the devise registration controller but due to following line it cause an error in devise registration controller
prepend_before_filter :require_no_authentication, :only => [ :new, :create, :cancel ]
The mentioned line on Devise's Controller makes sense in general cases: a logged in user can't sign up. As you're on a case where only an admin can create a user, I would suggest that you don't use Devise's controller on Registerable module and write your own controller with your own rules. You can write it based on Devise's controller changing only the mentioned line.
If you want to use it, try skipping the before_filter with skip_before_filter. I don't think it is the best solution. and I would write my own controller.
I was receiving the following error in my development log.
Filter chain halted as :require_no_authentication
An endless loop was created because devise's after_sign_in_path_for in application_controller.rb was redirecting back to the previous page with
stored_location_for(resource)
Devise's gem signs in the user when the password is edited.
Like you, I wanted an Admin user to be able to add new users. But I didn't want to mess with the Devise Registerable, since I actually wanted users to still be able to register themselves. I have some admin users with permission to add a new user, so I created additional methods in my users controller and additional views to handle that case.
My additional methods are not referenced by Devise's prepend_before_filter :require_no_authentication, so they don't get the error.
My recipe:
In app/controllers/users_controller.rb (or whatever object you are using devise for):
Copy the new, create and update methods and rename the copies to admin_new, admin_create, and admin_update.
In app/views/users, copy new.html.erb to admin_new.html.erb Change the partial to refer to admin_form instead of form:
<%= render 'admin_form' %>
Then copy the partial _form.html.erb to _admin_form.html.erb. In _admin_form.html.erb, change the form_for to use a different URL:
form_for(#user, :url => '/users/admin_create')
Add routes in config/routes.rb to point to the alternate methods in the user controller:
devise_scope :user do
...
get 'users/admin_new' => 'users#admin_new'
post 'users/admin_create' => 'users#admin_create'
end
Now you can add users while you are logged in by going to /users/admin_new, and users are still able to create their own user (register) using the devise mechanism that you have not disturbed.
I got an even simpler solution:
prepend_before_filter :require_no_authentication, only: [:cancel ]
By removing :new, :create from the prepend_before_filter it overrides devise source code and solve the problem. I had the same issue and it solved my problem.
I also noticed in my application that when I create a user and log in as that user, the above messages are displayed by the rails server console and I am redirected to rails localhost default window 'Yay, You are on Rails'.
This is because no page is defined to take the logged-in user. When I defined a welcome page 'index.html.erb' in a folder, say, 'welcome' under 'views' folder, the login was successful and it worked. You can try this.
I'm working through Michael Hartl's excellent tutorial on Rails, but I am having trouble with exercise 7 in Chapter 11.
This exercise is:
Add a nested route so that
/users/1/microposts shows all the
microposts for user 1. (You will also
have to add a Microposts controller
index action and corresponding view.)
I've done this successfully by changing my routes.rb file to read:
resources :users do
resources :microposts, :only => [:create, :destroy]
end
I am able to successfully call /users/1/microposts from a browser. However, most of the tests in microposts_controller_spec.rb are now broken. I receive the "no route matches" error when running autotest. For instance, the first test, which simply reads:
it "should deny access to 'create'" do
post :create
response.should redirect_to(signin_path)
end
now produces the following error:
1) MicropostsController access
control should deny access to 'create'
Failure/Error: post :create
No route matches {:controller=>"microposts",
:action=>"create"}
When I check rake routes
, I find this entry:
user_microposts POST /users/:user_id/microposts(.:format) {:action=>"create", :controller=>"microposts"}
which suggests the route does exist.
Has anyone else run into this issue while completing the tutorial? Is there a change I need to make in the spec file once I introduce nested routes? Does Rspec work with nested routes?
thanks
Because this is a nested route you will need to pass the user_id through:
some_user = way_of_creating_a_user_goes_here
post :create, :user_id => some_user.id
RSpec will attempt to go to the /microposts route without this parameter.