Axios + RailsでのPOSTの非同期化
What
Railsにおいて、GET以外のメソッド (POST, UPDATE, DELETE) を非同期で扱う際は、CSRF対策が施されています。
本記事は、非同期処理とは何か、そしてまた何であったかを知るための備忘録です。
下準備
ルーティング、コントローラー、モデル等を作成しておきます。
Rails.application.routes.draw do root 'main#index' post '/post', to: 'main#create' end
class MainController < ApplicationController def index end def create post = Post.create(post_params) end private def post_params params.permit(:title,:content) end end
class Post < ApplicationRecord end
class CreatePosts < ActiveRecord::Migration[5.2] def change create_table :posts do |t| t.string :title t.text :content t.timestamps end end end
view側は次のようにしておきます。Slimで書いています (cssとかは触りたくなかったため、brを多用していて汚い)。
ちなみに、formでsubmitを囲っておかないと、うまく発火しません。
# views/main/index.html.slim form[id='myForm'] | title: input[type='text' name='title' value='initial post'] br br | content: input[type='text' name='content' value='hello world wide web!!!'] br input[type='submit' value='submit data']
gemで非同期処理をする
jQueryはRailsにおいて、gemとして利用することができます。
gemとして利用した場合は、CSRF対策が施された状態なので、普通にPOSTなどができます。
$(function(){ $('#myForm').submit(function(e){ e.preventDefault(); var myData = { title: $('input[name="title"]').val(), content: $('input[name="content"]').val() } $.ajax({ url: '/post', type: 'post', data: myData, success: function(data){ console.log(data) }, error: function(){ console.log('error!!!') } }) }) })
$.ajaxの代わりに以下で書いても動きます。
var url='/post' $.post(url, myData).done(function(data){ console.log(data); })
上記は、/postに向けてPOSTメソッドを実行しています。
まず、ルーティングでmainコントローラーのcreateアクションが実行されます。
そのアクションで、paramsで保存された値をDBへ追加します。
Sequel Proでレコードを確認すると、きちんと保存できていることがわかります。
Axiosの場合
同じように書いてやります。
ここでは、getElementByIdが認識されなかったため、jQueryのメソッドですが、$(function(){})で囲って対処しています。
以下の書き方では、CSRF対策に引っかかり、POSTメソッドが失敗します。
$(function(){ var myForm = document.getElementById('myForm'); myForm.addEventListener('submit', function(e){ e.preventDefault(); var url = '/post' var myData = { title: document.querySelector('input[name="title"]').value, content: document.querySelector('input[name="content"]').value } axios.post(url,myData) .then(function(data){ console.log(data) }) }) })
以下のように、CSRFトークンを付け加える設定をすれば、AxiosでもPOSTメソッドの非同期化ができます。
$(function(){ // import axios from 'axios' axios.defaults.headers.common = { 'X-Requested-With': 'XMLHttpRequest', 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content') }; var myForm = document.getElementById('myForm'); myForm.addEventListener('submit', function(e){ e.preventDefault(); var url = '/post' var myData = { title: document.querySelector('input[name="title"]').value, content: document.querySelector('input[name="content"]').value } axios.post(url,myData) .then(function(data){ console.log(data) }) }) })