Xóa Nhiều Record Đã Lựa Chọn Bởi Checkbox Trong Rails 4
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 ...
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ức delete
- 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.