Reputation: 188
I have created a user signup page. When the user submits the form incorrectly, when displaying a validation error, it does not render on the same URL.
The signup form is located at this url:
http://localhost:3000/signup
I have added the following routes for the signup page:
resources :users
match '/signup', to: 'users#new', via: 'get'
When I submit the form, the model validation shows up but the url redirects to:
http://localhost:3000/users
I want the user to remain at the same url after submitting the form.
http://localhost:3000/signup
This is my controller code:
def new
@user = User.new
end
def create
@user = User.new(user_params) # Not the final implementation!
if @user.save
# Handle a successful save.
else
render 'new'
end
end
This is the beginning tag of my form:
<%= form_for @user, url: {action: "create"} do |f| %>
Upvotes: 6
Views: 1791
Reputation: 593
I believe that @Jaskaran's question is in regards to question 2 found at the bottom of Michael Hartle's Ruby on Rails Tutorial, section 7.3.3, so I will be answering in reference to that question:
- How does the URL on the unsubmitted signup form (Figure 7.12) compare to the URL for a submitted signup form (Figure 7.18)? Why don’t they match?
To answer this question, we need to understand how routing works in a Rails application. Let's walk through what happens when you visit each page and make a submission.
Your main page (home.html.erb
) contains a link to your signup page (new.html.erb
). That link looks like this:
<%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
The signup_path
is the part we are most interested in. signup_path
is a route helper and essentially tells Rails that when someone clicks on that link, Rails should behave as if they just went to your /signup
page. This is why the first URL you see (before submitting the form) shows http://localhost:3000/signup
.
Now let's take a look at what happens when your form is submitted. According to the new.html.erb
file, the form is contained within this Ruby code:
<%= form_for(@user) do |f| %>
. . .
<% end %>
You may remember from 7.2.2 that that Ruby code is actually rendered in HTML as:
<form class="new_user" id="new_user" action="/users" accept-charset="UTF-8" method="post">
. . .
</form>
What that is saying is that when the form is submitted, it will make a POST request to /users
- and that's the URL that you are seeing in your browser.
We can better understand why this is if we first stop to think - where does /users
route to? You can quickly check your routes by typing bundle exec rake routes
in your console. You should see it listed there:
Prefix Verb URI Pattern Controller#Action
users GET /users(.:format) users#index
POST /users(.:format) users#create
So any POST requests to /users
will be routed to the create
method of our users_controller.rb
. If you're wondering why that is, it is because we added this line to our routes.rb
file:
resources :users
More details on that line can be found here.
Upvotes: 2
Reputation: 3649
I'm working with Rails 5, but I suspect it's not too different conceptually.
In routes.rb:
get 'signup', to: 'users#new'
post 'signup', to: 'users#create'
resources :users
and in your form helper:
<%= form_for @user, url: signup_path do |f| %>
Essentially, the reason why it's not working as described in your original post is because when the form posts (rails 4.2 form helpers), it's tied to url: {action: "create"}
, which by default, according to the routes automatically generated for resources :users
, is post '/users', to: 'users#create
(rails 4.2 routing guide). And by searching top down in routes.rb, it'll see this first and you end up with http://localhost:3000/users
.
So, the changes I propose, should bind the form to post to the signup path instead which, in routes.rb, is seen as the second route entry.
Upvotes: 5