Gọi AJAX trong Rails 5.1 sử dụng jQuery (hoặc không :))
This post hasn't been updated for 7 years
Một phiên bản Rails không được đóng gói cùng jQuery được hiện thực hóa lần đầu tiên trong bản Rails 5.1. Trước kia, các phiên bản Rails vẫn thường phụ thuộc vào jQuery để có được chức năng Unobtrusive JavaScript nhưng bây giờ đã có thư viện rails-ujs
riêng với vai trò tương tự.
Một trong những chức năng sử dụng phổ biến nhất của jQuery trong Rails là khả năng gọi AJAX thông qua form và link. Nếu lần đầu tiên sử dụng Rails 5.1, bạn có thể ngỡ ngàng trước cách gọi AJAX mới, đặc biệt với những thứ như data format hay CSRF token.
Vì vậy nên tôi viết bài hướng dẫn nhỏ này nhằm giới thiệu một số phương pháp gọi AJAX hiệu quả:
1. Sử dụng rails-ujs (không jQuery)
Một app Rails 5.1 thường được tự động tích hợp thư viện rails-ujs
trong file application.js
:
//= require rails-ujs
Nếu không muốn include cho chung cả app, mà chỉ muốn sử dụng ở một số nơi nhất định, ví dụ như trong trường hợp muốn build riêng phần frontend bằng React, ta có thể sử dụng rails-ujs
bằng cách cài đặt như một package:
$ yarn add rails-ujs
Sau đó import và khởi động trong file JavaScript:
import Rails from 'rails-ujs'
Rails.start()
Tất nhiên là bỏ import tự động trong file application.js
:
//= require rails-ujs
Ví dụ ta muốn gọi một AJAX POST đến một API đầu cuối với data có dạng:
mydata = {
thing: {
field1: value1,
field2: value2,
}}
Việc gọi AJAX POST bằng rails-ujs
trông giống hệt như gọi bằng jQuery:
Rails.ajax({
type: "POST",
url: "/things",
data: mydata,
success: function(repsonse){...},
error: function(repsonse){...}
})
Ngoại trừ một điều: ta không thể truyền data dưới dạng JSON. Mà ta cần phải convert data theo kiểu application/x-www-form-urlencoded
, data sau khi convert có dạng:
mydata = 'thing[field1]=value1&thing[field2]=value2'
Bản thân jQuery cũng sử dụng chuẩn này để gọi AJAX, nhưng nó đã thực hiện ngầm bước này nên ta chỉ cần truyền JSON là có thể gọi được.
Hiện giờ tôi chưa tìm được đoạn doc nào nói về rails-ujs
tự động thực hiện việc này, nếu có xin hãy góp ý ở mục comment, tôi sẽ update bài sớm nhất có thể.
rails-ujs
tự động thêm CSRF token vào với request.
2. Sử dụng jQuery
Nếu việc convert data bằng tay khiến bạn nản trí, hoặc đơn giản là chưa quen với phương pháp mới, bạn vẫn có thể sử dụng jQuery như cũ. jQuery còn đảm nhận một số công việc khác trong app, vì vậy dưới đây tôi xin giới thiệu một số cách sử dụng jQuery trong Rails:
2.1. Sử dụng gem jquery-rails
Gem này được tích hợp tự động trong các phiên bản cũ của Rails. Bạn vẫn có thể cài đặt bằng cách thêm vào Gemfile
:
gem 'jquery-rails'
Rồi chạy:
$ bundle install
Sau đó thêm jquery
và jquery_ujs
vào file application.js
:
//= require jquery
//= require jquery_ujs
Đó là tất cả những gì cần làm. Bây giờ bạn có thể gọi AJAX như cũ:
$.ajax({
type: "POST",
url: "/things",
data: mydata,
success: function(data, textStatus, jqXHR){...},
error: function(jqXHR, textStatus, errorThrown){...}
})
jquery_ujs
lo việc thêm CSRF token và convert data một cách tự động.
2.2. Sử dụng jQuery package từ npm
Nếu không muốn sử dụng phiên bản jQuery được đóng gói trong gem, ta có thể cài đặt jQuery như một package bằng npm
:
$ yarn add jquery
$ yarn add jquery-ujs
Sau đó import vào file JavaScript:
import $ from ‘jquery’
import {} from ‘jquery-ujs’
Nhớ kiểm tra chắc chắn rằng bạn đã loại bỏ gem jquery-rails
trong Gemfile và hai thư viện jquery
và jquery_ujs
trong application.js
.
Nếu gặp báo lỗi không tìm thấy thư viện, trong webpack config ta thêm vào phần config.plugins
:
new webpack.ProvidePlugin({
$: “jquery”,
jQuery: “jquery”
}),
Và ta có thể dùng jQuery để gọi AJAX như bình thường.
3.Sử dụng axios
axios
là một thư viện dựa trên HTTP. Ta có thể sử dụng nó để tạo HTTP request từ node.js (trên server) và AJAX request từ brower.
Đây là một sự thay thế tốt nếu bạn không cần sử dụng các chức năng khác của jQuery. Để sử dụng axios
trong app Rails 5.1, đầu tiên ta cần cài đặt:
$ yarn add axios
Sau đó import vào file JavaScript:
import axios from ‘axios’
Ta có thể gọi AJAX theo như thế này:
axios({
method: 'POST',
url: '/things',
data: mydata,
headers: {
'X-CSRF-Token': document.querySelector("meta[name=csrf-token]").content
}
})
.then(function(response) {...},
.catch(function(error) {...}
})
Có một số điều cần lưu ý:
-
Ta phải tự thêm CSRF token vào header. Không giống như
jquery_ujs
vàrails-ujs
,axios
không tự động làm việc này. -
Ta có thể cài đặt làm chế độ mặc định để tránh lặp lại nhiều lần trong code:
const csrfToken = document.querySelector("meta[name=csrf-token]").content
axios.defaults.headers.common[‘X-CSRF-Token’] = csrfToken
- Ta có thể sử lý trường hợp gửi thành công và lỗi trả về trong hàm
then
.
Một phương pháp khác là sử dụng fetch, nhưng hiện tại API này vẫn đang được thử nghiệm và chưa hỗ trợ trên các trình duyệt. Vậy nên cách tốt nhất để sử dụng phương pháp này là sử dụng thư viện polyfill trên Github. Hiện tại các thông báo trả về đều cần được convert sang JSON trước khi sử dụng và việc sử lý lỗi khá rắc rối.
All Rights Reserved