Reputation: 1065
When handling validation errors in a User form on my rails project, I have the instruction render 'new'
if the user is not valid.
However, when this occurs, the url in the search bar changes.
Originally, it's https://localhost:3000/signup
but when the user submit the forms and the render 'new'
occurs, the URL becomes https://localhost:3000/users
Why is that?
Here's my routes.rb
Rails.application.routes.draw do
# Resources
resources :users, only: [ :new, :create ]
# Application root
root 'static_pages#home'
# Static pages
get '/help', to: 'static_pages#help'
get '/contact', to: 'static_pages#contact'
# Users
get '/signup', to: 'users#new'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Thanks,
Upvotes: 0
Views: 940
Reputation: 102001
In the Rails REST conventions you use different URI's to display the form to create a resource and for the forms action
attribute which you POST to.
Lets say you have:
resources :pets
This gives us:
GET /pets/new => pets#new
POST /pets => pets#create
We then have a typical form:
# posts to /pets
<%= form_for(@pet) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit %>
<% end %>
And a run of the mill controller:
class PetsController < ApplicationController
def new
@pet = Pet.new
end
def create
@pet = Pet.new(pet_params)
if @pet.save
redirect_to @pet
else
render :new
end
end
# ...
end
So when the user visits /pets/new
and fills in the form the browser url should read /pets
if the form is invalid. This is the intended behavior - posting to a different URL avoids a myriad of cache and history related issues.
From a restful standpoint its also correct - you're no longer viewing the new action - you're viewing the results of attempting to create a resource. The former is idempotent - the latter is not.
You need to recognize that the line render :new
is short for render template: 'pets/new'
. It does not redirect and it does not call the new
action in the controller. It simply renders the template and returns it as the response to the current request.
Upvotes: 2
Reputation: 10998
The reason for this is because when you submit your form, you're submitting it to some action from your new
view. The action that the form submits to has a path, and you can see what the path is by typing:
rake routes
in your console and searching for the create action. When your validation fails in the create action, you call render 'new'
.
When you render a template, the url of the page being rendered will be the url / path of the controller action that rendered the template.
In your case, whatever action you have that calls render 'new'
will be the one determing the url once your template is rendered.
Upvotes: 0
Reputation: 9692
The reason this is happening is because of the way Rails handles routes. Most likely, the form on your signup page has something like:
<?= form_for @user do |f| ?>
If you look at the generated HTML you'll notice that the form is POSTing to the url '/users'
. So when the signup form is submitted, the app is going to redirect you to /users
.
This is the normal behavior in Rails. (see Rails Guides)
If you want the URL to look like /signup
you can add a named route for it:
# Users
get '/signup', to: 'lead_magnets#new'
post '/signup', to: 'lead_magnets#create'
Then in your signup form you'll need to explicitly reference the new signup path:
<?= form_for @user, url: signup_path do |f| ?>
The generated HTML should look like
<form class="new_user" id="new_user" action="/signup" method="post">
Upvotes: 1
Reputation: 1292
Did you try to include recognize path?
Rails.application.routes.recognize_path
Upvotes: 0