Xóa Nhiều Record Đã Lựa Chọn Bởi Checkbox Trong Rails 4
Bài đăng này đã không được cập nhật trong 8 năm
Trong qúa trình phát triển ứng dụng web với Rails, mình gặp một vấn đề cần giải quyết đó là xóa đi một số records
mà người dùng lựa chọn trong danh sách các records
thông qua checkbox
.
Có rất nhiều cách để làm việc này, dưới đây mình trình bày 2 cách đó là
- xóa thông thường không sử dụng ajax
- xóa sử dụng ajax
Trước tiên để tiện theo dõi mình lấy một ví dụ là:
Mình có một bảng danh sách các products
được liệt kê theo dạng bảng và mỗi dòng có 1 nút chọn (checkbox) cho product
đó.
Một button
để submit
xóa các products
đã chọn.
Xóa không sử dụng ajax
Hiển thị dạng bảng như sau:
views/products/index.slim
= form_tag "", method: :delete, data: {confirm: "Are you sure?"}
table.table.table-striped.table-hover.table-bordered
thead
tr
th.text-center= t(".action")
th= t(".product_name")
th= t(".product_kind")
th= t(".jan_code")
tbody
- @products.each do |product|
tr
td.text-center= check_box_tag :product_ids, product.id, false,
class: "check-box-field"
td= product.name
td= product.product_kind
td= product.jan_code
= submit_tag "Xóa"
Tới đây mình sẽ có lựa chọn cho việc xóa các record đã checked.
- viết một hàm mới và tạo
collection
cho nó với phương thứcdelete
- tạo một controller mới và cho nó là
singular resource
Với cách thứ nhất thì sẽ không theo RESTful
có thể làm như sau
Trong products_controller.rb
def destroy_selected
if params[:product_ids]
Product.where(id: params[:product_ids]).destroy_all
end
redirect_to products_path
end
Trong routes.rb
resources :products do
collection do
delete :destroy_selected
end
end
Cấu hình routes như vậy cho mình đường dẫn destroy_selected_products_path
trỏ tới hàm destroy_selected
trên.
Sửa lại dòng sau trong products/index.slim
= form_tag "", method: :delete, data: {confirm: "Are you sure?"}
chuyển thành
= form_tag destroy_selected_products_path(product_ids: params[:product_ids]), method: :delete, data: {confirm: "Are you sure?"}
Như vậy khi submit
thì sẽ xóa các lựa chọn records
Tuy nhiên để tuân thủ RESTful
mình làm như sau
Tạo một controller
mới tên là bulk_products
rails g controller bulk_products destroy
Hàm destroy
trong controller này làm tương tự như destroy_selected
ở phía trên.
Trong routes.rb
cấu hình
scope :products do
resource :bulk_product
end
Cấu hình như vậy cho mình đường dẫn bulk_product_path
với phương thức delete
trỏ tới hàm destroy
Như vậy sửa lại dòng sau trong products/index.slim
= form_tag "", method: :delete, data: {confirm: "Are you sure?"}
Thành
= form_tag bulk_product_path(product_ids: params[:product_ids]), method: :delete, data: {confirm: "Are you sure?"}
Sử dụng ajax
Một số trường hợp mình không sử dụng cách thông thường như trên với form_tag
, do vậy mình sử dụng ajax
để làm việc này.
Về cơ bản thì vẫn là post một mảng các id
của products đã chọn để xóa lên server.
Mình vẫn sử dụng controller
là bulk_products
ở phía trên. Hàm destroy
sửa lại một chút như sau:
def destroy
if params[:product_ids].present?
Product.where(id: params[:product_ids]).destroy_all
end
respond_to do |format|
format.json{head :no_content}
end
end
Sửa lại views/products/index.slim
như sau
#destroy-selected-products.fa.fa-trash-o
#products
table.table.table-striped.table-hover.table-bordered
thead
tr
th.text-center= t(".action")
th= t(".product_name")
th= t(".product_kind")
th= t(".jan_code")
tbody
- @products.each do |product|
tr.product
td.text-center= check_box_tag :product_ids, product.id, false,
class: "check-box-field"
td= product.name
td= product.product_kind
td= product.jan_code
Như vậy khi mình lựa chọn các products
rồi bấm vào biểu tượng trash
(thùng rác) thì sẽ xóa các records
đó.
Thêm code
vào products.coffee
như sau:
$ ->
$("#destroy-selected-products").on "click", ->
product_ids = getSelectedCheckbox($("#products"))
confirm_msg = "Are you sure?"
if (product_ids.length > 0) && confirm(confirm_msg)
$.ajax
type: "DELETE"
dataType: "JSON"
url: "/products/bulk_product"
data: {product_ids: product_ids}
success: ->
$("#products").find(".check-box-field:checked").
parents(".product").remove()
return
getSelectedCheckbox = ($elem) ->
$elem.find(".check-box-field:checked").map((_, elem) ->
$(elem).val()
).get()
Như vậy mình đã thực hiện việc xóa nhiều records
lựa chọn bằng 2 cách.
All rights reserved