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と続けることができます。
以上です。