Thank you for your help. This gets confusing.
Today, when I started, I thought I had torn down my test rig and so I started testing on a different controller / view.
For form_with
with a model and no format specified:
<%= form_with model: import_file do |form| %>
produces
<form enctype="multipart/form-data" action="/import_files" accept-charset="UTF-8" method="post">
And as you said, a form_with
with a model and a format:
<%= form_with model: import_file, format: :json do |form| %>
produces
<form enctype="multipart/form-data" action="/import_files.json" accept-charset="UTF-8" method="post">
Hitting the submit button sends a JSON request. So, your conclusions are correct.
I then discovered that I did still have my test rig so I went back to it. This controller / model / view is called “registration”. Here are the pertinent parts:
The controller’s new method:
def new
@registration = Registration.new
end
The model:
class Registration
include ActiveModel::API
attr_accessor :username, :nickname
end
The form_with
:
<%= form_with model: @registration, remote: true, format: :json, data: { turbo: false } do |form| %>
The routes:
resource :registration, only: %i[new create] do
post :callback
end
resolve('Registration') { [:registration] }
As the Reddit post explains, on the page I have 8 of these forms with the remote, format, and turbo options toggling between all 8 combinations. In all of these forms, the path is just /registration
and the .json
suffix is missing. Here is the first example:
<form data-turbo="false" action="/registration" accept-charset="UTF-8" method="post">
Had I experimented with the import_file model / view / controller before, I would have noticed that the format worked there but not on the registration trio. My guess right now is somehow the model is the difference.
And, indeed, if I hack the registration#new method to be:
def new
@registration = ImportFile.new
end
now the forms have registration.json
as their path.
So, the net net net is that somehow my Registration active model is causing this.