Search code examples
ruby-on-railsruby

Rails: How does form_with know, which Controller-action to invoke?


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?


Solution

  • 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.