How to use custom view to update user via devise? (rails gem) - ruby-on-rails

I have 2 custom views I built for devise, 1 changes the password the other updates other custom information. The password update worked, so I copied the method for the second view, however I am getting an error when submitting the data
No route matches [PATCH] "/users/discovery_settings/update"
which does not make sense because my route is
devise_for :users, controllers: {registrations: 'users/registrations'}
as :user do
end
get 'users/discovery_settings' => 'users#discovery_settings'
post 'users/discovery_settings/update' => 'users#update_discovery'
in my controller i user the same method that works for password updates
def update_discovery
#user = User.find(current_user.id)
if #user.update(user_params)
# Sign in the user by passing validation in case their password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
end
then i call it in my form_for view
<%= form_for(#user, :url => { :action => "update_discovery" }, html: {class: "form floating-label"}) do |f| %>
Any ideas how to fix the routing error?
I am at a lost as to why it is looking for "patch" when i have already specified "post"

The error's telling you. You have a POST route and the update is asking for a PATCH route.
try with patch instead of post:
patch 'users/discovery_settings/update' => 'users#update_discovery'

Related

how to configure new update method in routes

At this time I want to create a new method with the same functionallity than update default method so I did it like this, the method's name is 'updatepaso1' from a file called 'editpaso1.html.erb'
editpaso1.html.erb
<%= simple_form_for([#persona, #caracterizacion],
:url => url_for(:action => 'updatepaso1', :controller => 'caracterizaciones'),
:method => 'get') do |f| %>
content form
<% end %>
caracterizaciones_controller.rb
def updatepaso1
if #caracterizacion.update(caracterizacion_params)
redirect_to editpaso2_persona_caracterizacion_path(#persona, #caracterizacion), notice: 'Paso2 Finalizado Correctamente'
else
render action: 'editpaso1'
end
end
and routes.rb
resources :personas do
resources :caracterizaciones do
collection do
get :updatepaso1 # < --
get :updatepaso2
end
member do
get :editpaso1
get :editpaso2
get :editpaso3
end
end
end
If I try to do it from a default 'update' method it works's ok, but in this case when I update the information with that method the app redirect this url
http://localhost:3002/personas/2/caracterizaciones/updatepaso1
And should redirect this one after update the information
http://localhost:3002/personas/2/caracterizaciones/1/editpaso2
so I think the problem is the configuration in routes for that 'updatepaso1' method
thanks for your help

RESTful way of updating a model from different view

My application has a User model.
In the home#index view, I present a form for the current User to update their email address, using form_for.
Now if my application is to remain RESTful, as I understand it the Haml in app/views/home/index.html.haml should look something like:
- form_for current_user, :url => { :action => "update", :controller => "user" } do |f|
= f.text_field :email
= f.submit "Update email address"
My question is as follows: what is the correct way to get the User model to redirect to the home#index view after the update?
You can give redirect to your format.html on your controller def update, like
format.html { redirect to :back }
this will redirect to the page that send request before.
That's the simplest way..!
In this case I actually reverted to using resourceful routes... far cleaner.
Thanks for the other suggestions.

Rails 3 with Devise: No route matches /d/users/sign_out

I am getting the following error when I try to sign out of devise error:
No route matches [GET] "/d/users/sign_out"
My tag is correct, it is as follows:
<%= link_to "Sign Out", destroy_session_path, :method=>:delete %>
My route for devise is:
devise_for :users, :path_prefix=>"d", :controllers=>{:sessions=>"sessions"}
Other routes are:
resources :users#For CRUD defined after devise_for like in Devise Wiki
With a custom controller sessions for ajax login like on the Devise wiki page:
class SessionsController < Devise::SessionsController
def create
respond_to do |format|
format.html{ super }
format.json do
resource = warden.authenticate!(:scope => resource_name, :recall => "#{controller_path}#failure")
#resource = warden.authenticate!(:scope => resource_name, :recall => :failure)
return sign_in_and_redirect(resource_name, resource)
end
end
end
def sign_in_and_redirect(resource_or_scope, resource=nil)
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource ||= resource_or_scope
sign_in(scope, resource) unless warden.user(scope) == resource
return render :json => {:success => true, :redirect => stored_location_for(scope) || after_sign_in_path_for(resource)}
end
def failure
return render:json => {:success => false, :errors => ["Login failed."]}
end
end
The devise initializer has:
config.sign_out_via = :delete
Any ideas on what could be causing the problem? I've searched Google and am still stumped.
Update:
Here is a screenshot of the rails routes file for the devise users. Sorry, it is small, but you can right-click then view it by itself for a larger screen.
Update #2:
The jquery_ujs file is included.
Update #3:
It appears in the console that delete is indeed being passed, but it is jumping from the sessions_controller to / then to d/users/sign_out...Not sure how to fix this.
Update #4:
When redirecting it goes first to d/users/sign_out as DELETE, as it should. It then redirects to root_url which then gives the error ERROR Errno::ECONNABORTED: An established connection was aborted by the software in your host machine. It then tries to redirect to d/users/sign_out as GET where it is failing.
This appears to be an issue between Devise and Ruby 1.9.2-p290. Updating to Ruby 1.9.3 and running bundle update to ensure the latest version of Devise was used; appears to work.
It sounds like you might have removed //= require jquery_ujs from your application.js file. I think that handles the link particulars to make a 'delete' request. Either way, as it is now, you're making a 'GET' which obviously won't hit your destroy_user_session method.
Change:
config.sign_out_via = :delete
to:
config.sign_out_via = :get
See this related:
No route matches "/users/sign_out" devise rails 3

How do I maintain the same controller & action in a page URL upon re-rendering an action in Rails?

I am using AuthLogic to authenticate users in my rails app. That part is set up and workign properly.
I have the following route defined:
map.login '/account/login', :controller => :user_sessions, :action => :new
Calling rake routes returns what I expect:
login /account/login {:controller=>"user_sessions", :action=>"new"}
When someone submits a login, it calls UserSessionsController.create:
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Login successful!"
redirect_back_or_default account_url
else
render :action => :new
end
end
If #user_session.save fails, the appropriate error messages appear on the screen. However, the browser URL also changes to "http://localhost:3000/user_session" instead of staying on "http://localhost:3000/account/login".
I assume the problem is what I am feeding to the render method. What should I be feeding it?
This is actually the intended behavior for this process. In a standard scaffolded RESTful controller, a validation error in the create and update actions will simply render the original template without redirecting. This results in what you are seeing – the new template will be displayed with the create action's URL in the URL bar. The reason for this is that in order to display information to the user about what errors occurred, the view must have access to the invalid model object, which is #user_session in your case.
You can use redirect_to instead of render if you want to force a redirect to the original URL, but this will cause you to lose information about the errors. You would need to manually persist the errors in the session, which would be messy. My advice is not to worry about the fact that the URL doesn't match that of the original as this is pretty standard in all Rails apps.
Just adding solution for Rails 4 (based on Shaun's answer here):
Add new route to routes file:
post '/carts/new' => 'carts#create', as: :create_post
Add url: create_post_path to form tag
Done.
After further digging, I found the solution in another StackOverflow question: Use custom route upon model validation failure
I simply modified my routes to add a new one for posing to '/account/login':
map.login '/account/login', :controller => :user_sessions, :action => :new, :conditions => {:method => :get}
map.login_post '/account/login', :controller => :user_sessions, :action => :create, :conditions => {:method => :post}
Then, I updated my view to utilize the new route:
<% form_for #user_session, :url => login_post_path do |f| %>
This works perfectly. A failed login gives the appropriate error messages and maintains the '/account/login' URL.

No action respond to id in rails routing problem

I am adding a functionality of resetting password in my rails application
In my users page , i have all the users listing
If i am logging in as a admin below the users a link to reset password to users are available which will set a default password to them
<%= link_to "Reset Password",reset_password_user_path %>
In my controller users
def reset_password
#user = params[:user]
puts "which user #{#user}"
#user.password = "12345"
if #user.save
flash[:notice] = "Password successfully reseted"
redirect_to user_path
else
flash[:error]= "Password not reste!"
redirect_to user_path
end
end
In my routes
map.resources :users, :member => {:reset_password => :post}
When i run my users page , i am getting the error as below
reset_password_user_url failed to generate from {:action=>"reset_password", :controller=>"users"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["users", :id, "reset_password"] - are they all satisfied?
WHen i gave the link as
<%= link_to "Reset Password",reset_password_user_path(user) %>
then i am getting the error as No action respond to 2
Processing UsersController#2 (for 127.0.0.1 at 2011-03-14 11:38:33) [GET]
Parameters: {"action"=>"2", "id"=>"reset_password", "controller"=>"users"}
How to resolve this..
Alternatively <%= link_to "Reset Password", reset_password_user_path(user), :method => "post" %> assuming you have Prototype or jQuery.
This way you are still posting to the action as it makes changes to the user.
Try with get method instead of post in routes.

Resources