Rails and FormData
Articles about Rails and FormData. I write both in English and Japanese.
This post talks about using WebAPI's FormData with Rails.
Recently, I replaced Rails Form with an API-based system. In other words, instead of Form, I worked with the backend with an XHR request (axios).
We recently migrated from using Rails formstoanAPIbasedappwheredataissenttothebackendusingXHRrequests(inourcase,usingaxios).
This article uses a typical user model.
For the following example I will be using a generic User model.
<%= form_for @user, url: {action: "create"} do |f| %>
<%= f.text_field :name %> # "Yokoyama"
<%= f.text_field :role %> # "Developer"
<%= f.submit "Create" %>
<% end %>
If you use Rails Form, you will find the following params in the controller.
If we were using Rails forms then we'd normally get:
def create
# params = <ActionController::Parameters
# {
# "user" => {
# "name"=>"Yokoyama",
# "role"=>"Developer"
# },
# "controller"=>"...",
# "action"=>"create",
# }
# permitted: false>
...
end
When I made the request body, I used FormData.
When packaging a body for a POST/PATCH request we used FormData.
const formData = new FormData();
formData.append('name','Yokoyama');
formData.append('role','Developer');
const url = 'user create link';
axios.post(url, formData, {
headers: {
'content-type': 'multipart/form-data',
},
})
...
The Rails Controller has the following response.
On the Rails backend we get:
def create
# params = <ActionController::Parameters
# {
# "name"=>"Yokoyama",
# "role"=>"Developer",
# "controller"=>"...",
# "action"=>"create",
# }
# permitted: false>
...
end
Key Point: --Because the attributes are top-level, problems with the same name can occur. --It's not a Rails pattern.
As you can see:
Originally written by @jugtuttle on Medium, but with the model name as the key If it is included, it is a success.
@jugtuttle on Medium pointed out that you can simply use a key that has the model name. So in our case:
const formData = new FormData();
formData.append('user[name]','Yokoyama');
formData.append('user[role]','Developer');
axios.post('insert user path here', formData, {
headers: {
'content-type': 'multipart/form-data',
},
})
...
To make it easier:
To make it even easier:
// rails_form_data.js
class RailsFormData extends FormData {
constructor(model) {
super();
this.model = model;
}
append(key, value) {
super.append(`${this.model}[${key}]`, value);
}
}
export default RailsFormData;
import RailsFormData from '...'
const formData = new RailsFormData('user');
formData.append('name','Yokoyama');
formData.append('role','Developer');
axios.post('insert user path here', formData, {
headers: {
'content-type': 'multipart/form-data',
},
})
...
The Rails controller has the following states:
Then on the Rails backend side you'll get:
def create
# params = <ActionController::Parameters
# {
# "user" => {
# "name"=>"Yokoyama",
# "role"=>"Developer"
# },
# "controller"=>"...",
# "action"=>"create",
# }
# permitted: false>
...
end
Recommended Posts