Rails form not invoking create controller method on POST - ruby-on-rails

I have the following form in my /app/views/password_resets/new.html.erb view
<% form_tag password_resets_path do %>
<label><%= t(:email) %>:</label><br />
<%= text_field_tag "email" %><br />
<br />
<%= submit_tag t("reset_password") %>
<% end %>
along with a controller called PasswordResetsController containing a create method:
def create
#user = User.find_by_email(params[:email])
if #user
#user.deliver_password_reset_instructions!
self.notice = t("password_reset_instructions_are_mailed")
redirect_to root_url
else
flash[:error] = t("no_user_found")
render :action => :new
end
end
When I go to /password_resets/new, fill out the form, and submit, the create method is invoked properly, since the PasswordResetsController::create() method is invoked when a POST happens to /password_resets.
However, when I put the form in another view, say, /app/views/test/index.html.erb, fill out the form, an submit, I get
Unknown action
No action responded to index. Actions:
access_forbidden, admin_created?,
check_roles, create, edit, find_order,
included, new, role_requirements,
role_requirements=, title, title=, and
update
Any ideas why transplanting the form is not working?

Turns out the issue was related to SSL. This showed up in the log:
Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
The page I had the form on required SSL, and Rails did not like me submitting the form from an SSL page to to a non-SSL one. So, as a workaround, since I'm using ssl_requirement, I just put
ssl_required :all
in the password_resets controller, and now things work.

Related

Rails 4 & Devise 4: Keep user on current page after updating profile

I have a User model, and I am hoping to have different pages to edit their info so that I don't have everything on edit.html.erb
So far I have created views for page_content.html.erb and donation_options.html.erb which have my forms on them. Both work as intended and successfully update my User, but after submitting the form I am redirected the User root, which is show.html.erb. I would like to set it up so that the user stays on the current page after updating their profile. I am not sure if I need to edit my UsersController, or create a new controller, or take a different approach.
Here's an example of my form:
<%= form_for #user do |f| %>
<!--Some inputs-->
<div class="actions">
<%= f.submit 'Update', :class => "btn btn-primary" %>
<!--After submitting, I'm taken to /users/:id/. I'd like to stay on /users/:id/current_view-->
</div>
<% end %>
If you already have a UsersController you should set something up comparable to this:
Class UsersController < ApplicationController
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to your_path_here
end
end
end
I am not sure exactly what your UsersController looks like, but that should give you an idea. After a user is updated, use redirect_to with your path you would like the User sent to. You may also use redirect_to :back if you are looking to redirect back to the current page you are on.
Please see this existing SO post.

Ruby on Rails - redirect_to

I'm having some trouble understanding the redirect_to statement.
I have a model "Book" (with an boolean attribute "read")and a controller "books". Now I created a second controller "Admins" having to methods: index and change.
The index view just renders a list off all Books with a link to the change method:
<% #Books.each do |d| %>
<%= d.title %><br>
<% if d.read==true %>
<%= link_to "mark unread", change_path(:id=>d.id)%>
<% else %>
<%= link_to "mark read", change_path(:id=>d.id)%>
<%end %>
Now the change method just changes the "read" attribute:
#book=Book.find(params[:id])
if #book.read==true
#book.update_attributes(:read => false)
else
#book.update_attributes(:read => true)
end
redirect_to action: "index"
The Problem is: rails tries to redirect me to the show action using the :id as a parameter...(perhaps because the change_url is /admins/change?id=3)
But I just want to be directed back to the index view "/admins"
is there a way? it seems like rails always tries to redirect to the view action if there is an id as a parameter
Thanks alot
PS: the routes.rb contains resources:admins and resources:books
Use this
redirect_to :controller => 'admins', :action => 'index'
Or
redirect_to admins_url
The above two will direct you to the index page of AdminsController. There is no way that Rails would route it to show action UNLESS you are redirecting to show action from the index action of AdminsController. Since, you did not share index action code of AdminsController, I would recommend you to check there.
If you want a clear explanation of redirect_to ... checkout
https://gist.github.com/jcasimir/1210155
I had a kind of similar issue some days ago. I would suggest to do this within the form where you list the books and the mark/unmark checkboxes.
<%= form_for #book,:url => book_index_path do |f| %>
This worked fine for me, when I set up a site where you create data and the user is immediately redirected to the same page (incl. success/error message).. to do a kind of
human batch-processing.

Possible to add a form into another models view in rails

I have a very small application I ma building in rails. It is a simple weight tracker app. I have created a User model which has a sign up page. Once the user logs in they are redirected to the user#show view. Here is the user controller so far:
class UsersController < ApplicationController
before_filter :authenticate_user!
def show
#user = current_user
end
end
I have 2 other models one is a Weight model and the other a Goal model, I would like it so what when a user signs up they are presented with a screen asking them to type in the current weight and goal weight this information will then be store in the Weight and Goal models respectively along with the logged in users ID.
So far I have been able to add a form to the user show.html.erb template :
<%= form_for #user do |f| %>
<%= f.fields_for :weight do |builder| %>
<fieldset>
<%= f.label :value, "Current weight" %><br />
<%= f.text_field :value %><br />
</fieldset>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Which renders the form correctly but when I then click on the submit button it simply goes to an error page saying Unknown action- The action 'update' could not be found for UsersController. Im assuming iM doing something wrong as it should try and send to the create action.
Is there anyone out there who could help me back on the right path, Im very much a noob at rails.
Well this has nothing to do with all your models. This pertains to the fact you have not defined an update method in your controller.
When you have done that look into accepts_nested_attributes_for if you want to nest models.
Besides all that, a show page usually shows a read only for of the object. An edit page has the editable form of the object.
You are using the form_for Rails helper and passing #user to it, because #user is a persistent model (saved in the db) then the generated form will have the action to /users/:id with PUT method so the request will be sent to an action named update in your UsersController, it seems that you don't have that action defined in your UsersController
it should be somthing like the following:
def update
#user = Users.find(params[:id])
if #user.update_attributes(params[:user])
# do something if saving succeeds
else
# do something if saving fails
end
end
I believe, after searching for this question having similar issues, that it is not update that is missing but edit.
I know this is an old thread, and you have probably solved the issue, but if not try adding this:
def edit
#user = User.find(params[:id])
end

Rails - Redirect_to error in controller - "The page isn't redirecting properly" "

In the process of learning Rails so excuse my noob question.
What I want to do:
There is a text_field_tag that allows a user to enter an item id. I then want to get that value and use it as a parameter in the url.
ex.
The user types '4Qe6' into the text box and clicks submit. Then the page navigates to 'trckr.net/tracker/track/4Qe6'
Here is the code for my form:
<h1>Tracker#index</h1>
<p>This is the landing page</p>
<p>
<u> Track an item: </u>
<%= form_tag(:action => 'track') do %>
Item ID: <%= text_field_tag(:id) %>
<%= submit_tag('Track Item') %>
<% end %>
</p>
And in TrackerController:
class TrackerController < ApplicationController
def index
end
def track
puts "navigating to track view"
#id = params[:id]
redirect_to "/tracker/track/#{#id}"
end
end
But I'm getting the error:
The page isn't redirecting properly - Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
However, if I link directly to a page like this:
<%= link_to("Track item 2", {:action => 'track', :id => '6969'}) %>
It works fine. Here is my output when I run rake routes:
Calvins-Air:trckr Calvino$ rake routes
root / tracker#index
/:controller(/:action(/:id))(.:format) :controller#:action
If I use a different action, I can't use the instance variable I set in the controller.
New Controller Code:
def track
puts "navigating to track view"
end
#redirects to track after retrieving the url parameters
#want a url parameter so users can link to the page
def track_helper
#id = params[:id]
redirect_to "/tracker/track/#{#id}"
end
But then the track view, #id can't be accessed:
<h1>Tracker#track</h1>
<p>This page will be used to view an items details</p>
<p><b>Item id: <%= #id %> </b></p>
<%= link_to("Back to index" , {:action => 'index'}) %>
EDIT: Fixed that last error by declaring the #id variable in the track action. Fixed code:
def track
puts "navigating to track view"
#id = params[:id]
end
I guess that's because your redirect path is handled by the same action(and controller) from where you are sending this request. You can either create a new action for it or route this to a different handler.

What is the best way to route a static controller in Rails?

I have a static_controller that is in charge of all the static pages in the site and works as follows in routes.rb:
map.connect ':id', :controller => 'static', :action => 'show'
I have a static page called about that among other information, has a contact form.
I currently have a contacts_controller that is in charge of inserting the contact information to the database.
Inside my routes.rb file, I have:
map.resources :contacts
My contact form (simplified) looks like this:
<% form_for #contact do |f| %>
<p class="errors"><%= f.error_messages %></p>
<p>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</p>
<p class="buttons"><%= f.submit %></p>
<% end %>
Which in turn submits to the create action of my contacts_controller.
My create action looks like this:
def create
#contact = Contact.new(params[:contact])
if #contact.save
flash[:notice] = "Email delivered successfully."
end
redirect_to "about"
end
The problem is, is the that when I redirect back to my about page the error_messages for the form get lost (since the error_messages for the form only exist for one request, and that request ends upon redirect).
How would I go about preserving the error_messages and still linking the users back to the about static url?
Would a session/flash be sufficient (if so, what code would I use to pass error messages) or am I going about this whole thing wrong?
Thanks!
I think what might be going on is you need to render rather than redirect.
Redirect terminates the request, and tells the client to make a new request to a different address. That will lose your errors.
If your save attempt fails your want to complete the request by rendering the action again with the errors shown.
def create
#contact = Contact.new(params[:contact])
if #contact.save
flash[:notice] = "Email delivered successfully."
redirect_to #contact #make a new request for the address of the new record or some other address if you want
else
render :action => "new" #complete the request by rendering the new action with the #contact variable that was just created (including the #errors).
end

Resources