Wallace Johnson
Wallace Johnson

Reputation: 23

Migrating from `form_for` over to the new `form_with`

How would one go about converting from form_for over to form_with for the following:

<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>

I've looked through Rails' form_with documentation but haven't found any relevant examples.

Thanks!

Upvotes: 2

Views: 1346

Answers (3)

Ammar Shah
Ammar Shah

Reputation: 149

You don't have to worry about the as: resource_name and html: { method: :post } in this case. Simply use the model: resource in form_with and you are good to go.

As per the documentation:

model infers both the URL and scope.

So, using this

<%= form_with model: Post.new do |form| %>
  ...
<% end %>

is equivalent to something like:

<%= form_with scope: :post, url: posts_path do |form| %>
  ...
<% end %>

But since Devise uses a different helper method, password_path in this case, to generate certain URL. You only need to use the url: option along with model: in form_with like below:

<%= form_with(model: resource, url: password_path(resource_name)) do |form| %>

will generate something like:

<form action="/users/password" accept-charset="UTF-8" method="post">

Upvotes: 0

max
max

Reputation: 102368

form_with has the scope: option that changes input name prefixes, ids and the for attribute of labels. As far as I can tell it does the exact same thing as the as: option for form_for.

:scope - The scope to prefix input field names with and thereby how the submitted parameters are grouped in controllers.

# Adding a scope prefixes the input field names:
<%= form_with scope: :post, url: posts_path do |form| %>
  <%= form.text_field :title %>
<% end %>
# =>
<form action="/posts" method="post" data-remote="true">
  <input type="text" name="post[title]">
</form>

https://api.rubyonrails.org/v6.0.0/classes/ActionView/Helpers/FormHelper.html#method-i-form_with

So the equivalent call is:

<%= form_with(
      model: resource, 
      scope: resource_name, 
      url: password_path(resource_name), 
      method: :post
    ) do |f| %>

Upvotes: 5

Vasfed
Vasfed

Reputation: 18504

Try

= form_with model: resource, scope: resource_name,
            url: password_path(resource_name), method: :post do |f|

also form_with does not generate classes and ids for elements, if you need these - add them manually

Documentation in api is much more detailed than in guides at the moment.

Upvotes: 1

Related Questions