6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RailsとFormData

Last updated at Posted at 2020-11-11

eyecatch.jpg

Rails and FormData

RailsとFormDataについての記事です。英語と日本語で両方書きます。

This post talks about using WebAPI's FormData with Rails.

最近RailsのFormからAPIを基にしたシステムに交換しました。つまり、Formの代わりにXHRのリクエスト(axios)でバックエンドと連携しました。

We recently migrated from using Rails forms to an API based app where data is sent to the backend using XHR requests (in our case, using axios).

この記事で典型的なユーザモデルを使用します。

For the following example I will be using a generic User model.

問題・Problem

RailsのFormを使用・Using Rails Form

<%= form_for @user, url: {action: "create"} do |f| %>
  <%= f.text_field :name %> # "Yokoyama"
  <%= f.text_field :role %> # "Developer"
  <%= f.submit "Create" %>
<% end %>

RailsのFormを利用したら、controllerに以下のparamsがあります。

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

FormDataを使用・Using FormData

リクエストボディーを作ると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',
            },
          })
...
    

RailsのControllerに下記レスポンスがあります。

On the Rails backend we get:

def create
 # params = <ActionController::Parameters
 # {
 #  "name"=>"Yokoyama",
 #	"role"=>"Developer",
 #	"controller"=>"...",
 #	"action"=>"create",
 # }
 # permitted: false>
  ...
end

キーポイント:

  • 属性はトップレベルのため、同名前の問題が起こる可能性があります。
  • Railsのパタンではありません。

As you can see:

  • All attributes are scoped to the top level, which will cause issues if there are name conflicts
  • It's also just against the typical Rails pattern

解決・Solution

もともと@jugtuttle on Mediumが書いた解決ですが、モデルの名前をキーに含まれたら成功です。

@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 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',
            },
          })
...
    

結果・Result

Railsのcontrollerには以下状態があります。

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
6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?