Taken this form as an example:
<%= form_with model: @product do |f| %>
<!-- ... --!>
<% end %>
The routes-file:
get "/products", to: "products#index"
get "/products/new", to: "products#new"
post "/products", to: "products#create"
get "/products/:id", to: "products#show", as: "product"
How does it know that it has to invoke it create-action of the products-controller?
What is the decision based upon?
form_with
guesses the route from the model. If the model is an instance of Product
and it is a new_record?
then is will POST /products
. When it is a persisted?
record, then it will PATCH /products/{:id}
(see Form Helpers
in the official Rails Guides).
This is in line with Ruby on Rails conventions and the default way for defining routes with rescources :products
(see Routing). Which would generate the following routes:
GET /products => ProductsController#index
GET /products/new => ProductsController#new
POST /products => ProductsController#create
GET /products/:id => ProductsController#show
GET /products/:id/edit => ProductsController#edit
PATCH/PUT /products/:id => ProductsController#update
DELETE /products/:id => ProductsController#destroy
Note when you do not use the resources
helper to generate routes, when from_with
only works when you define the same routes that Rails would do. Otherwise, we will need to pass an additional url:
to the form helper.
I suggest reading about FormHelper#form_with
in the Rails' API docs and taking a look at this method's implementation.