Stimulusの習作: Rails.fireのかわりにRails.ajaxまたはfetchで送信

内容

Stimulusの習作: ドラッグ・アンド・ドロップ(クライアント側)
Stimulusの習作: ドラッグ・アンド・ドロップ(サーバ側)
上記では隠しフォームとRails.fireを用いてBook ID群をクライアントからサーバへ送信しました。今回はつくりを変更してRails.ajaxまたはFetch APIを用いて送信したいと思います。

参照

CSRF保護
2020/04/19 Rails セキュリティガイド - Railsガイド
2017/10/23 RailsのCSRF保護を詳しく調べてみた(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

Rails.ajax
2019/10/18 ajax · rails-jquery-ujs Wiki
2020/04/19 rails-ajax.coffee at v6.0.2.2 · rails-rails
XMLHttpRequestを用いて実装されていました。
2020/04/19 rails-csrf.coffee at v6.0.2.2 · rails-rails

Fetch API
2019/03/19 Fetch API - Web API | MDN

Rails.ajax

app/javascript/controllers/drag_item_controller.js

  dragend(event) {
   const nodes = this.element.querySelectorAll('[data-book-id]')
   const ids = Array.from(nodes).map(el => el.getAttribute('data-book-id'))
   const payload = new FormData()
   payload.append('row_order', ids)
   Rails.ajax({
     url: '/books/row_order',
     type: 'PATCH',
     dataType: 'json',
     data: payload,
     error: (_response, _status, xhr) => {
       Turbolinks.visit('/books')
     },
   })
 }

Book ID群は、FormDataとして送信します。
X-CSRF-Tokenは、Rails.ajaxが付けてくれます。

Rails.ajaxの実装は、以上になります。

Fetch API

app/javascript/controllers/drag_item_controller.js

  dragend(event) {
   const nodes = this.element.querySelectorAll('[data-book-id]')
   const ids = Array.from(nodes).map(el => el.getAttribute('data-book-id'))
   const obj = { row_order: ids }
   const body = JSON.stringify(obj)
   const token = document.getElementsByName('csrf-token')[0].content
   const headers = {
     'X-CSRF-Token': token,
     'Accept': 'application/json',
     'Content-Type': 'application/json',
   }
   fetch('/books/row_order', {
     method: 'PATCH',
     // credentials: 'same-origin',
     headers: headers,
     body: body,
   })
   .then(response => {
     if (!response.ok) {
       Turbolinks.visit('/books')
     }
   })
 }

Book ID群は、JSON.stringify()のまま設定します。
X-CSRF-Tokenをheadersに設定します。
認証情報は、未使用(コメントアウト)にしました。

app/controllers/books_controller.rb

  # PATCH /books/row_order(.:format)
 def row_order
   ActiveRecord::Base.transaction do
     params[:row_order].each_with_index do |id, i|
       book = Book.find(id)
       book.row_order = i + 1
       book.save!(validate: false)
       # book.save!
     end
   end
 end

row_orderを配列で受け取れるため、each_with_indexと続けることができます。

以上です。



この記事が気に入ったらサポートをしてみませんか?