In my ruby on rails project, I am using devise as the authentication plugin. Now I have added the change password functionality to the project and when submit the form, I'm getting an error No route matches "/users/update_password"
This is my update password code
def update_password
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
# Sign in the user by passing validation in case his password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
This is my route details
resources :users, :only => [] do
collection do
get 'current'
get 'edit'
post 'update_password'
end
end
and this is my edit form
<div id="loginForm">
<div id="loginHeader"><h3>Change Password</h3></div>
<div id="loginContent">
<%= form_for(#user, :url => { :action => "update_password" }) do |f| %>
<p><%= f.password_field :current_password, :class => "login_txt", :placeholder => "We need your current password to confirm your changes", :autocomplete => "off" %></p>
<p><%= f.password_field :password, :class => "login_txt", :placeholder => "New password", :autocomplete => "off" %></p>
<p><%= f.password_field :password_confirmation, :class => "login_txt", :placeholder => "Confirm password", :autocomplete => "off" %></p>
<p>
<input id="user_submit" name="commit" type="submit" value="Update Password" class="login_btn" />
</p>
<% end %>
</div>
</div>
Can anyone help me how to fix this issue
Thanks a lot
In your routes.rb you define update_password as a POST action on the collection (/users/update_password), but in your form you are implicitly defining it as a PUT action when you pass #user to form_for, since #user already exists.
I haven't tested this, but I believe that changing your route on the collection from a POST to a PUT should fix this:
resources :users, :only => [] do
collection do
get 'current'
get 'edit'
put 'update_password'
end
end
See also: Rails 3.0.10, customer routes, post and form_for tag
Related
I setup a platform that uses Devise to create and manage users and CanCanCan to manage permissions. Users have a role (admin or client) that allows them access to certain areas. Admin users have the ability to can :manage, :all
I extended Devise so that I have a users/registrations and users/sessions controller.
Admin users have access to views in a ManagerController dashboard that allows them to manage other users. I've figured out how to show the details of a different user, but I can't figure out how to save the information. I get errors that indicate it either can't find the User or that it requires a POST route.
I'm fairly new to Rails, so it could be something simple. I was able to find solutions that included the regular Devise installation, but not the extension. I feel like the problem may be in my routes.
I also can't create new users from here either.
Routes.rb
get 'users' => 'manager#users'
get 'users/edit' => 'manager#edit'
post 'users/edit' => 'manager#edit'
get 'users/new' => 'manager#new'
devise_for :users, :controllers => { registrations: 'users/registrations', sessions: 'users/sessions' }
devise_scope :user do
authenticated :user do
root 'users/registrations#edit', as: :authenticated_root
end
unauthenticated do
root 'users/sessions#new', as: :unauthenticated_root
end
end
Manager Controller
class ManagerController < ApplicationController
authorize_resource :class => false
include ManagerHelper
def users
#users = User.where.not(:id => current_user.id)
end
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
flash[:notice] = "Successfully created User."
redirect_to root_path
else
render :action => 'new'
end
end
def edit
#user = User.find(params[:id])
#companies = Company.all
end
def update
#user = User.find(params[:id])
params[:user][:id].delete(:password) if params[:user][:password].blank?
params[:user][:id].delete(:password_confirmation) if params[:user][:password].blank? and params[:user][:password_confirmation].blank?
if #user.update(user_params)
flash[:notice] = "Successfully updated User."
redirect_to root_path
else
render :action => 'edit'
end
end
end
private
def user_params
params.require(:user).permit(:email, :first_name, :last_name, :company_id, :role, :password, :password_confirmation)
end
end
ManagerHelper
module ManagerHelper
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
Manager/Edit.html.erb
<h2>Edit <%= resource_name.to_s.humanize %></h2>
<%= form_for(resource, :as => #user, :url => edit_user_registration_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
<%= f.hidden_field :id %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
</div>
<div class="field">
<%= f.label :first_name %><br />
<%= f.text_field :first_name%>
</div>
<div class="field">
<%= f.label :last_name %><br />
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :company %><br />
<%= f.collection_select :company_id, #companies, :id, :name, prompt: true %>
</div>
<div class="field">
<%= f.label :role %><br />
<%= f.text_field :role %>
</div>
<div class="field">
<%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
<%= f.password_field :password, autocomplete: "new-password" %>
<% if #minimum_password_length %>
<br />
<em><%= #minimum_password_length %> characters minimum</em>
<% end %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
</div>
<div class="actions">
<%= f.submit "Update" %>
</div>
<% end %>
I would like the updated information to be saved to the User database.
Currently, I get this error when I click update after changing the user info.
ActiveRecord::RecordNotFound in ManagerController#edit
Couldn't find User without an ID
Weirdly, when I see the User info, the url is: http://localhost:3000/users/edit?id=2
But when I update (and get the error), the url changes to: http://localhost:3000/users/edit.user
I would also like to be able to create New Users from this screen.
Currently, the user form populates with the information of the user who is logged in. (To be fair, I have been trying to get the edit user correct before tackling this issue.)
I think You want to update existing user info.
If that is the case:
I find your url path is wrong
:url => edit_user_registration_path(resource_name)
you donot have to user registration here .
If the admin going to update info
in routes file . some thing like this
namespace :admins do
resources :users
end
then use the path creatd from this
Many tries later, I've found a solution. There were a lot of errors, so bear with me.
Routes.rb -- Was using the wrong URL in the form submission, so needed to add the routes for the Update function in the Manager controller.
get 'users/edit' => 'manager#edit'
post 'users/edit' => 'manager#edit'
get 'users/update' => 'manager#update'
post 'users/update' => 'manager#update'
Manager Controller -- I had to change the password rules so that I could update without a password. Similar concept, slightly different execution.
def update
#user = User.find(params[:user][:id])
#companies = Company.all
if params[:user][:password].blank? && params[:user][:password_confirmation].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
if #user.update(user_params)
flash[:notice] = "Successfully updated User."
redirect_to root_path
else
render :action => 'edit'
end
end
Rendered Form.html.erb - Updated with newly created URL path.
<%= form_for(resource, as: #user, url: users_update_path(resource_name)) do |f| %>
<%= render "devise/shared/error_messages", resource: resource %>
In my current Ruby on Rails project, the devise plugin has been used for authentication. To change the password, I added the devise plugin's passwords/edit.html.erb file into the user directory in my project. Everything's working fine except the error messages are not showing.
This is my current update_password method
def update_password
#user = User.find(current_user.id)
if #user.update_with_password(params[:user])
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
I've mentioned the require validation in the user model as follows
validates_presence_of :name, :primary_locale, :current_password, :password, :password_confirmation
This is my edit form code:
<div id="loginForm" class="editPwFormHeight">
<div id="loginHeader"><h3><%= image_tag("wif_small.png"); %></h3></div>
<div id="loginContent">
<%= form_for(#user, :url => { :action => "update_password", :locale => params[:locale] }, :method => "post") do |f| %>
<%= f.hidden_field :reset_password_token %>
<p><%= f.password_field :current_password, :class => "login_txt", :placeholder => I18n.t('wi.common.enterCurrentPw'), :autocomplete => "off" %></p>
<p><%= f.password_field :password, :class => "login_txt", :placeholder => I18n.t('wif.common.newPw'), :autocomplete => "off" %></p>
<p><%= f.password_field :password_confirmation, :class => "login_txt", :placeholder => I18n.t('wif.common.confirmPw'), :autocomplete => "off" %></p>
<p>
<input id="user_submit" name="commit" type="submit" value="<%= I18n.t('wif.common.updatePw') %>" class="login_btn" />
<input id="user_cancel" name="commit" type="button" value="<%= I18n.t('wif.common.cancel') %>" class="login_btn" />
</p>
<% end %>
</div>
</div>
Anyone can help me to solve this issue. I wanted to show the error message if the user has not typed the current password, or any other error which are currently supporting by the devise
You need to add the following line to your template:
<%= devise_error_messages! %>
You can customise the messages themselves by editing Devise's translation files, e.g. config/locales/devise.en.yml
If you're not using devise's built-in controllers, then you will need to register the DeviseHelper module as a helper in your controller using the helper method.
I am using rails 3 with gem devise.Devise has built in method for change password.But i want
that admin can reset password of any user and how i can do it please help..
You can define custom method and also define routes for it
<%= form_for(:user, :url => {:controller => '/administrator', :action => 'change_password',:id => #user.id}, :html => {:id => 'admin_update_form',:method => :put}) do |f| %>
<div class="change-pass">
<h2>Change Passwords</h2>
<div class="pass-detail">
<div class="username-btn">
<label>Passwords</label>
<%= f.password_field :password, :class=> 'fields' %>
</div>
<div class="username-btn" style="margin-bottom:40px;">
<label>Confirm Passwords</label>
<%= f.password_field :password_confirmation, :class=> 'fields' %>
</div>
<%=hidden_field_tag 'user_ids',:id => 'user_ids' %>
<div class="username-btn_button">
<%= f.submit 'change password', :id => 'password_btn' ,:class => 'reg-findjob'%>
</div>
</div>
</div>
In controller code
def change_password
#user = User.find(params[:id])
if #user.update_attributes(:password => params[:user][:password], :password_confirmation => params[:user][:password_confirmation])
flash[:notice] = 'Password was changed successfully.'
render :text => 'ok'
else
flash[:error]=[]
#user.errors.full_messages.each do |error|
flash[:error] << error
end
end
In controller find user and update its password attribute.I am sending user id with form
whose password is to changed or you can do it according your requirement.
Sorry for the novice question but I am trying to get to grips with RoR. I have a very basic sign up and login process in place but am having some difficulty getting the routing correct. I am also unsure whether I am actually being logged out successfully when I push my logout button because it isn't then displaying the login button as it should.
My setup is as follows on Rails 3.1:
Sessions Controller
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by_email(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to root_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password!"
render "signup"
end
end
def destroy
session[:user_id] = nil
redirect_to root_url, :notice => "Logged Out!"
end
end
User Controller
class UserController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new (params[:user])
if #user.save
redirect_to root_url, :notice => "Signed Up!"
else
render "user/new"
end
end
end
User Model
class User < ActiveRecord::Base
has_secure_password
validates_confirmation_of :password
validates_presence_of :password, :on => :create
validates_presence_of :email
validates_uniqueness_of :email, :on => :create
end
Sessions/new.html.erb
<h1>Log In</h1>
<%= form_tag login_path do %>
<div class="field">
<%= label_tag :email %>
<%= text_field_tag :email, params[:email] %>
</div>
<div class ="field">
<%= label_tag :password %>
<%= password_field_tag :password %>
</div>
<div class="actions"><%= submit_tag "Log in" %></div>
<%end%>
User/new.html.erb
<% if session[:user_id] %>
<!-- user is logged in -->
<%= link_to logout_path %>
<% else %>
<!-- user is not logged in -->
<%= link_to login_path %>
<% end %>
<h1>Sign Up</h1>
<%= form_for #user do |f| %>
<% if #user.errors.any? %>
<div class="error_messages">
<h2>Form is invalid</h2>
<ul>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class = "field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<div class = "field">
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div class = "field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</div>
<div class="actions"><%= f.submit %></div>
<% end %>
Finally my Routes file
MadeByV2::Application.routes.draw do
controller :user do
get "signup" => "user#new"
end
resources :users
controller :sessions do
get "login" => "sessions#new"
post "login" => "sessions#create"
delete "logout" => "sessions#destroy"
end
root :to => "user#new"
end
Sorry for the extensive use of code in this post but I figure it's best to give a well rounded view of everything so people can see where I am going wrong.
Any help you can offer really would be much appreciated because I don't seem to be getting it myself
Thanks,
Tom
Your code looks fine, but your routes look a little strange.
I'd try something like this:
resources :users
resources :sessions
match 'login' => 'sessions#new', :as => :login
match 'logout' => 'sessions#destroy', :as => :logout
Then I think everything you've currently got should work.
I am making a Rails 3.1 app and have a signup form that was working fine, but I seemed to have changed something to break it.. I'm using Twitter bootstrap and twitter_bootstrap_form_for gem. I made some change that messed with the formatting of the form fields, but more importantly, when I submit the Sign Up form to create a new User, the information is showing up in the URL and looks like this:
EDIT: This is happening in the latest versions of Chrome and Firefox
http://localhost:3000/?utf8=%E2%9C%93&authenticity_token=UaKG5Y8fuPul2Klx7e2LtdPLTRepBxDM3Zdy8S%2F52W4%3D&user%5Bemail%5D=kevinc%40example.com&user%5Bpassword%5D=testing&user%5Bpassword_confirmation%5D=testing&commit=Sign+Up
Here is the code for the form:
<div class="span7">
<h3 class="center" id="more">Sign Up Now!</h3>
<%= twitter_bootstrap_form_for #user do |user| %>
<%= user.email_field :email, :placeholder => 'me#example.com' %>
<%= user.password_field :password %>
<%= user.password_field :password_confirmation, 'Confirm Password' %>
<%= user.actions do %>
<%= user.submit 'Sign Up' %>
<% end %>
<% end %>
</div>
Here is the code for the UsersController:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to about_path, :notice => "Signed up!"
else
render 'new'
end
end
end
Not sure if there is more you need but if so let me know! Thank you!
Edit: For debugging I tried specifying :post and also using a plain form_for
<%= form_for(#user, :method => :post) do |f| %>
<div class="field">
<%= f.label :email %>
<%= f.email_field :email %>
</div>
<div class="field">
<%= f.label :password %>
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation %>
</div>
<div class="actions"><%= f.submit "Sign Up" %></div>
<% end %>
This gives me the same problem as above.
Adding routes.rb:
Auth31::Application.routes.draw do
get "home" => "pages#home"
get "about" => "pages#about"
get "contact" => "pages#contact"
get "help" => "pages#help"
get "login" => "sessions#new", :as => "login"
get "logout" => "sessions#destroy", :as => "logout"
get "signup" => "users#new", :as => "signup"
root :to => "pages#home"
resources :pages
resources :users
resources :sessions
resources :password_resets
end
The problem was that I was specifying the HTML form tag when Rails form_for generates its own. See below to add a class to a form:
<%= form_for(#user, :html => { :class => "form-stacked"} ) do |f| %>
This worked fine. I'm still not sure why having 2 tags would generate a GET request.
It looks like your for is sending a GET request, rather that a POST request. I'm not sure why this is happening (have you tried using plain form_for for debugging purposes?), but you should be able to fix it my explicitly setting the method:
<%= twitter_bootstrap_form_for(#user, :method => :post) do |user| %>