Routing Error when trying to update Devise user details, Rails 4 - ruby-on-rails

I am trying to fix issues with changing Devise user details in Rails 4 project. Based on this question
Layout:
<div class="modal fade" id="user-profile" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog log-modal">
<div class="modal-content">
<%= render partial: "shared/profile" %>
</div>
</div>
</div>
_profile partial.
<%= form_for(#user, :url => { :action => "update_password",:controller =>"users" } ,remote: true, format: :json) do |f| %>
<div class="form-group">
<%= f.text_field :name,:class=>"user-input form-control", :id=>"user-name" ,:placeholder=> "Lietotājvārds*",:"data-parsley-group"=>"f1" %>
</div>
<div class="form-group">
<%= f.email_field :email ,:class=>"user-input form-control", :id=>"password",:placeholder=> "E-pasts *",:"data-parsley-group"=>"f2" %>
</div>
<div class="form-group">
<%= f.password_field :current_password, :autocomplete => "off" ,:class=>"user-input form-control", :id=>"password",:placeholder=> "Vecā parole* ",:"data-parsley-group"=>"f3" %>
</div>
<div class="form-group">
<%= f.password_field :password , :class=>"user-input form-control", :id=>"password",:placeholder=> "Jaunā parole* vismaz 8 simboli ", :"data-parsley-group"=>"f3" %>
</div>
<div class="form-group">
<%= f.password_field :password_confirmation , :class=>"user-input form-control", :id=>"password",:placeholder=> "Atkārtot paroli * vismaz 8 simboli ", :"data-parsley-group"=>"f3" %>
</div>
<button type="submit" class="blue-button btn btn-default">Apstiprināt</button>
<%end%>
My routes file:
Rails.application.routes.draw do
get 'banned/index'
get 'reusable/login'
get 'reusable/registration'
get 'reusable/password_recovery'
resources :menus
resources :blocked do
collection do
get 'checktoken'
get 'checkemail'
end
member do
post 'toggle'
post 'rev'
end
end
ActiveAdmin.routes(self)
scope "(:locale)", :locale => /lv|ee|ru/ do
devise_for :users, :controllers => {:registrations=> "registrations"}
resource :user, only: [:edit] do
collection do
patch 'update_password'
end
end
resources "successful-registration", :controller => :successful_registration, :as => :successful_registration
resources :replies do
member do
put "like", to: "replies#upvote"
put "dislike", to: "replies#downvote"
end
end
resources :reviews do
member do
put "like", to: "reviews#upvote"
put "dislike", to: "reviews#downvote"
put "downwote", to: "reviews#complaints"
end
end
resources :reports
resources :offers
resources :messages
resources :feedbacks
resources :girls do
collection do
get 'checktoken'
get 'checkemail'
end
member do
put "like", to: "girls#upvote"
put "dislike", to: "girls#downvote"
post 'toggle'
end
end
get 'sms/receive/', to: 'sms#receive'
root 'girls#index'
end
end
Log file:
Started POST "/ru/user/update_password" for 212.93.100.35 at 2015-10-03 14:08:12 +0300
ActionController::RoutingError (No route matches [POST] "/ru/user/update_password"):
actionpack (4.1.6) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
actionpack (4.1.6) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
railties (4.1.6) lib/rails/rack/logger.rb:38:in `call_app'
What I tried:
1) Restarted server
2) Tried to change order of the user routes.
I have no other ideas to try. Any help ?
Thanks in advance.

It seems you have routing for PATCH request (patch 'update_password') but you are sending POST request.
Edit your routing file (post 'update_password') or use PATCH request:
<%= form_for(#user, :url => { :action => "update_password",:controller =>"users",method: "patch" },remote: true, format: :json) do |f| %>

As an addition to the answer, you should also be considering how Devise would provide you with user account change functionality:
# # 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"}
If you use rake routes, you'll see which Devise routes you have access to, and which you're able to use.
If you're looking to use Devise to handle this (which it appears you are), you can either use the above routes (which will become accessible if you add :recoverable to your User model Devise definitions), or if you call them directly.
If you want to add / edit Devise routes explicitly, you'll be able to do the following:
devise_for :users, controllers: { registrations: "registrations" } do
patch "passwords/update" => "passwords#update", :as => :password_update
end
--
I also see a lot of your routes being specifically defined. Although nothing wrong with this, it's very inefficient and actually prevents your app from being able to harness its true potential.
Here are some examples I would recommend you investigate:
#config/routes.rb
resources :reusable, only: [] do
collection do
get :login
get :registration
get :password_recovery
end
end
Another one is to define multiple resources in one batch...
resources :reports, :offers, :messages, :feedbacks

Related

Devise update password route

On a rails app setup with Devise, i am trying to provide users with a form to change passwords.
i have followed the solution 3 from the Devise wiki:https://github.com/heartcombo/devise/wiki/How-To:-Allow-users-to-edit-their-password
and accordingly have in a user controller
class UsersController < Devise::RegistrationsController
def update_password
#user = current_user
if #user.update(user_params)
# Sign in the user by passing validation in case their password changed
bypass_sign_in(#user)
redirect_to root_path
else
render "edit"
end
end
end
routes.rb
devise_for :users,
path: "", path_names: {
sign_in: "login",
sign_out: "logout",
sign_up: "register",
edit: "settings"
},
controllers: {
registrations: "users",
sessions: "users/sessions"
}
resources :users do
patch 'update_password'
end
Rake routes gives me :
user_update_password_path POST (/:locale)/users/:user_id/update_password(.:format)
users#update_password {:locale=>/fr|en|de/}
the link to access the menu is the following:
<%= link_to user_update_password_path(current_user) %>
in browser, that links directs me to :
http://localhost:3000/en/users/1/update_password
but I receive a Routing error
No route matches [GET] "/en/users/1/update_password"
When I wrap the
resources :users do
resources :wishlists
collection do
patch 'update_password'
end
end
the link_to send to
http://localhost:3000/1/password
Which results in the error
undefined local variable or method `user_update_password_path' for
<#:0x00007f86cfe48f10> Did you mean? user_password_path
however, rails routes shows:
update_password_users PATCH (/:locale)/users/update_password(.:format) users#update_password {:locale=>/fr|en|de/}
but a link_to
update_password_users_path
results in an error
Could not find devise mapping for path "/en/users/update_password".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/some/route" => "some_devise_controller" end
2) You are testing a Devise controller bypassing the router. If so,
you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
What have I missed ?
First of all in the solution 3 it says resource not resources. Watch the differences carefully between yours and the below one -
resource :user, only: [:edit] do
collection do
patch 'update_password'
end
end
Second the like should direct to edit_user_path not update_password_user as that is the patch route.
Third, you have to add a edit action to your controller as the wiki suggests. And also a form for the action.
before_action :authenticate_user!
def edit
#user = current_user
end
and in app/views/users/edit.html.erb
<%= form_for(#user, :url => { :action => "update_password" } ) do |f| %>
<div class="field">
<%= f.label :password, "Password" %><br />
<%= f.password_field :password, :autocomplete => "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<div class="action_container">
<%= f.submit %>
</div>
<% end %>
You missed lots of things. Try reading the wiki again.

Routing in Rails forms

I've used a form successfully in embedded Ruby that looks like this:
<%= form_for :comment, url: user_comments_path do |c| %>
<%= c.text_field :location %>
<%= c.text_field :title %>
<%= c.text_field :body %>
<%= c.submit ("Submit") %>
<% end %>
However when I tried to put this into Bootstrap I came up against problems. I then tried to make a simpler HTML form like this:
<form accept-charset="UTF-8" action="user/comments" method="post">
<input id="comment_location" name="comment[location]" type="text"/>
<input id="comment_title" name="comment[title]" type="text"/>
<input id="comment_body" name="comment[body]" type="text"/>
<input name="commit" type="submit" value="Create"/>
</form>
...but I came up against the same error message: No route matches [POST] "/users/1/comments/new/user/comments". I am using nested resources, and Rails routes in the terminal tells me that the user_comments path 'POST' equates to user/user_id/comments and the Create controller action.
In my HTML form if I enter action="user/comments" then the resulting path is "/users/1/comments/new/user/comments", if I enter action="comments" the path is "/comments", and if I enter "/" the path is "/". The path that I'm trying to reach is "user/comments" but there seems to be no way there through my HTML form.
I've racked my brains but I can't understand why this might be. Any help would be much appreciated! Thanks
ps. Routes look like this:
Rails.application.routes.draw do
get 'sessions/new'
get 'welcome/index'
root 'welcome#index'
get 'user' => 'users#show'
get 'login', to: 'sessions#new'
post 'login', to: 'sessions#create'
delete 'logout', to: 'sessions#destroy'
get "log_out" => "sessions#destroy", :as => "log_out"
get "log_in" => "sessions#new", :as => "log_in"
get "sign_up" => "users#new", :as => "sign_up"
root :to => "users#new"
resources :users do
resources :comments
end
resources :sessions
end
update routes.rb use collection instead of resources to get /users/comments like path
resources :users do
collection do
get 'comments'
end
end

getting No route matches [POST] "/login/log_in"

im using gem parse-ruby-client and im trying to create a login. and when the login is successful then i want to go to a welcome#index
here is my login_controller.rb
class LoginController < ApplicationController
def index
end
def log_in
#user = Parse::User.authenticate(params[:user][:username], params[:user][:password])
end
end
index.html.erb
<div class="Log_in_Form">
<h4><center>Log in with your existing "app_name" account</center></h4>
<%= form_for(:user, :url => {:controller => 'login', :action => 'log_in'}) do |f| %>
<center><p> Username:</br> <%= f.text_field :username%> </p></center>
<center><p> Password:</br> <%= f.password_field :password%></p></center>
<center><h4><%= f.submit :Login %></h4></center>
<% end %>
</div>
routes.rb
Rails.application.routes.draw do
get 'welcome/index'
root 'login#index'
get 'login/log_in' => 'login#log_in'
end
you need to have an post route or your login. change your routes to this one (if you need the get route also)
Rails.application.routes.draw do
get 'welcome/index'
root 'login#index'
get 'login/log_in' => 'login#log_in'
post 'login/log_in' => 'login#log_in'
end
or change
get 'login/log_in' => 'login#log_in'
to
match 'login/log_in' => 'login#log_in', via: [:get, :post]

Why do I get NoMethodError in Games#new for my game form but the analog for my Users#new

I am creating a a site in RoR and and I have built the user signup and login forms. Everything works great. The thing is, I went to create another object called games, which functions almost identically to users, but when I try to interact with it I get an error. I built the forms almost exactly the same and the routing I congruent.
Here is my user new.html.erb:
<!DOCTYPE html>
<html>
<body>
<% provide(:title, 'Sign up') %>
<h1 class="heading1" >Sign up</h1>
<br>
<div>
<%= form_for(#user, :html => { :class => 'form' }) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name %>
<br>
<%= f.label :email %>
<%= f.text_field :email %>
<br>
<%= f.label :username %>
<%= f.text_field :username %>
<br>
<%= f.label :password %>
<%= f.password_field :password %>
<br>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation %>
<br>
<br>
<%= f.submit "Create my account", class: "submit" %>
<% end %>
</div>
</div>
</body>
</html>
and my users controller new and create methods:
def create
#user = User.new(user_params)
if #user.save
sign_in #user
redirect_to #user
else
render 'new'
end
end
def new
#user =User.new
end
private
def user_params
params.require(:user).permit(:name, :email, :username, :password,
:password_confirmation)
end
end
and my game new.html.erb:
<!DOCTYPE html>
<html>
<body>
<h1 class="heading1" >Create Game</h1>
<br>
<div>
<%= form_for(#game, :html => { :class => 'form' }) do |i| %>
<%= i.label :title %>
<%= i.text_field :title %>
<br>
<br>
<%= i.submit "Create Game", class: "submit" %>
<% end %>
</div>
</div>
</body>
</html>
and my game controller:
def create
#game = Game.new(game_params)
if #game.save
redirect_to root_url
else
render 'create'
end
end
def new
#game = Game.new
end
private
def game_params
params.require(:game).permit(:title)
end
end
and my routing file:
Rails.application.routes.draw do
resources :sessions, only: [:new, :create, :destroy]
resources :users
match '/new_game', to: 'games#new', via: 'get'
match '/signup', to: 'users#new', via: 'get'
match '/signin', to: 'sessions#new', via: 'get'
match '/signout', to: 'sessions#destroy', via: 'delete'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'home#home'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end
The rails server error page reads:
NoMethodError in Games#new
Showing /Users/Karen/Desktop/BR2/app/views/games/new.html.erb where line #7 raised:
undefined method `games_path' for #<#<Class:0x007fbfd6bdb260>:0x007fbfd6bd8948>
Extracted source (around line #7):
4
5
6
7
8
9
10
<h1 class="heading1" >Create Game</h1>
<br>
<div>
<%= form_for(#game, :html => { :class => 'form' }) do |i| %>
<%= i.label :title %>
<%= i.text_field :title %>
<br>
Rails.root: /Users/Karen/Desktop/BR2
Application Trace | Framework Trace | Full Trace
app/views/games/new.html.erb:7:in `_app_views_games_new_html_erb___3427370169918602482_70230959128880'
Request
Parameters:
None
I really appreciate all and any help. if there is any more information I can provide please say so.
Thank you
The best option is to add games specific RESTful routes in routes.rb
resources :games
and remove match '/new_game', to: 'games#new', via: 'get' route.
Doing this will give you the following Restful routes:
Prefix Verb URI Pattern Controller#Action
games GET /games(.:format) games#index
POST /games(.:format) games#create
new_game GET /games/new(.:format) games#new
edit_game GET /games/:id/edit(.:format) games#edit
game GET /games/:id(.:format) games#show
PATCH /games/:id(.:format) games#update
PUT /games/:id(.:format) games#update
DELETE /games/:id(.:format) games#destroy
So upon form submission your application would route to create action (games_path) by HTTP Post request.
Currently you have just defined a single route for games resource which routes to new action with
match '/new_game', to: 'games#new', via: 'get'
But there is no route for create action which is why you receive the error as undefined method 'games_path' on the form
If you don't wish to use the RESTful routes(resources :games) then you would have to define a route as:
match '/games', as: 'games', to: 'games#create', via: 'post'
for create action.
You will find that when you do bundle exec rake routes in your console, you have not actually created named routes for your games paths.
If you're using match and you want to name a route (so you have something like games_path available), you'd have to do this:
match `/games`, as: 'games', to: 'games#index', via: :get
A much easier way is to use resources for most of your routes, and just go with the default RESTFUL paths:
resources :games
# Now you have access to '/games/new', '/games/:id',
# '/games', etc, as well as names such as `games_path`.
# Check `bundle exec rake routes` for all of them.
See Rails Routing for more information

No route matches {:action=>"show", :controller=>"users"}

I'm trying to implement a Twitter Boostrap login form, that's gonna be used on every page (because the navigation bar is a part of the layout).
However, when trying the code below I get the following error:
No route matches {:action=>"show", :controller=>"users"}
User controller:
class UsersController < ApplicationController
def index
#users = User.all
end
def show
...
end
def login
...
end
end
_navigation.html.erb:
<div class="dropdown-menu" style="padding: 15px; padding-bottom: 0px;">
<%= form_for("user", :url => user_path) do |f| %>
<%= f.label :email%>
<%= f.text_field(:email, :size => 30, :class => 'login_field', :placeholder => 'Användarnamn')%>
<%= f.label :password%>
<%= f.text_field(:password, :size => 30, :class => 'login_field', :placeholder => 'Lösenord')%>
<%= f.submit "Logga in", :class => 'login_submit btn btn-primary' %>
<% end %>
</div>
config/routes.rb:
get "home/index"
resources :users
resources :projects
resources :tickets
root :to => 'home#index'
rake routes (that has to do with users):
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
I'm new to Rails but find it strange that it complains that the route doesn't exist because the action "show" is to be found inside the user controller.
The other thing I'm wondering about is why it looks for the action "show", while it should be "login" in this case?
Why is this happening and what shall I do?
your error is in this line
<%= form_for("user", :url => user_path) do |f| %>
user_path is expecting an id. if you change that to users_path, that should fix it but I don't think that's your intention.
UPDATE: to use the login action on the users controller, you need to update your routes
resources :users do
post :login, on: :collection, as: :login
end
passing the :as option creates a named_route for you called login_users_path which you can use on your form_for. and since we wanted to do a post, we also need to specify that in the form_for
<%= form_for("user", :url => login_users_path, :html => { :method => :post }) do |f| %>
Update your routes.rb to look like:
get "home/index"
resources :users do
post :login, :on => :collection
end
resources :projects
resources :tickets
root :to => 'home#index'
and in your view file change the form_for line to be:
<%= form_for("user", :url => login_users_path) do |f| %>
resources :users only adds default routes. If you want to add new action (other then defaults) you need to use 'collection. And you can specify the method get or post. After adding to routes.rb. You can get the path by running rake routes then you add the correct route in the action of form.
resources :users, :collection => {:login => :post}

Resources