TL;DR:
class ResourcesController < ApplicationController
def new
@resource = Resource.new(resource_params)
if resource_params.present?
@resource.validate
end
end
def create
@resource = Resource.new(resource_params)
if @resource.save
redirect_to @resource, notice: 'Resource has been created'
else
redirect_to new_resource_url(resource: resource_params)
end
end
private
def resource_params
params.fetch(:resource, {}).permit(...)
end
end
I asked this myself as well in my early beginner days, on why Rails scaffold generator generates the def create
action to render :new
if saving failed, instead of redirecting to the correct URL just something like above, which would confuse the users because their URL would have changed from /resources/new
into /resources
even though they would still see the exact same Resource form on the page, and therefore they would not be able to reload the page or copy this /resources
URL (for example, if they want to share this URL to someone else), because should they share this /resources
URL, the others would see a list of Resources on the page instead of what the original user would have expected to see from the copied URL: which is the form page.
After the user submits the form, the URL they see on the address bar should have changed into POST http://localhost:3000/resources
instead of just simply http://localhost:3000/resources
. The browser hides the HTTP Method being used, that's why this leads to their possible confusion that /resources
seems to have been both sometimes: a form page, sometimes a list of resources page. However, speaking of UX, every time anyone enters something or pastes something in the URL address bar of the browser, it is always automatically implied to be doing a GET
request. Therefore, it makes sense for the browser-developers to just simply hide the HTTP method (i.e. GET
in particular) from the users as to not confuse them.
From my answer above, I only used something like this once before (because there was a certain action that demanded me not to change the URL from the referrer form page). However, I normally render :new
instead of redirect_to new_resources_url
, simply because:
a redirect_to new_resource_url(resource_params)
would take twice as much time and data-transmitted than simply rendering :new
. Why? Because you redirect (opening up a new request) with the exact same parameters anyway. Just imagine if your form page is soooo big, and has so many input fields.
and also that there's a limit to how long a URL can be, of which won't guarantee to work if you have a very big form with very long text fields. See this SO
Updated:
As you have said though, why not just POST /resources/new
instead of POST /resources
when the form is submitted, right? This will solve the redirect_to new_resource_url(resource_params)
problem I've shown above, because the URL after form-submit would have been the same and you can just simply render :new
, then. And I actually agree on that, and I've used something like this also before long time ago. The main reason I don't use this is that it is not inline with REST standards. That is: POST /resources/new
means that you're creating a Resource object "inside" the resources/new
location, which then means by REST, after submitting the form, I would and should be able to access this newly created resource by doing something like GET /resources/new/the_newly_created_record
, except that... you can't.
But you can still use POST /resources/new
, although I would not recommend it on a normal Rails application like yours, and however strictly discourage it on an API-based Rails application.