Custom Template File CSV Export in Rails Application

Bài viết này mình giới thiệu tới các bạn cách Export và custom template file CSV trong Rails Application. Ví dụ ở đây mình cần Export thông tin bảng User

Step-1. Thêm dòng lệnh sau vào file config của app :

require 'csv'

Step-2. Tạo đường dẫn trong routes

resources :users do
  collection { post :import }
end

Step-3. Trong model User ta thêm như sau để sinh ra CSV data

Chú ý, trong bảng User có rất nhiều cột Rails sinh ra mà mình không muốn lấy như ID, created_at, updated_at ... khi đó mình sẽ khai báo 1 biến constant để thiết lập lại những trường cần lấy như sau

EXPORT_PARAMS = %i[user_name email name name_kana date_of_birth postal_code
    address1 address2 address3 building_name tel]
def to_csv
  desired_columns = (User::EXPORT_PARAMS).map &:to_s
  CSV.generate do |csv|
    csv << desired_columns
    all.each do |user|
      csv << user.attributes.values_at(*desired_columns)
    end
  end
end

Step-4. Trong users_controller.rb gọi method export to_csv trong model ra bằng khối lệnh respond_to

class UsersController < ApplicationController
  def index
    @ users = User.all
    respond_to do |format|
      format.html
      format.csv do
         headers["Content-Disposition"] = "attachment; filename=\"user-list.csv\""
         headers["Content-Type"] ||= "text/csv"
      end
    end
  end
end

Ở đây, mình custom filename export ra là user-list.csv và template được định nghĩa lại trong file index.csv.erb

Step-5. Custom tempalte file CSV khi export, mình nhúng file csv vào ruby như sau index.csv.erb

<% headers = User::FIELD_NAMES.map{|field| t("user.attributes.#{field}")} %>
<%= CSV.generate_line headers %>
<% @users.each do |user| %>
  <% row = User::USERS_EXPORTS.map{|field| user.send field} %>
  <%= (CSV.generate_line row, row_sep: ?\t).html_safe %>
<% end %>

Các constant FIELD_NAMES, USERS_EXPORTS định nghĩa các trường mà bạn cần export ra

  FIELD_NAMES = %i[login_id email name name_kana date_of_birth postal_code
    address1 address2 address3 building_name tel]

  USERS_EXPORTS = %w[user_name email name name_kana birthday
    postal_code address1 address2 address3 building_name tel]

Ở đây chúng ta có thể dễ dàng custom tittle các cột trong file csv export để I18n ở khai báo headers

row_sep giúp tạo khoảng trắng giữa headers và body trong template file csv khi export, các bạn có thể tham khảo thêm các thuộc tính khác trong doc để custom cho phù hợp với template cần export

Step-6. Cuối cùng trong view, gọi method download trong controller


  <%= link_to t("common.export_csv"),
    users_path(format: "csv"), class: "btn btn-primary" %>
  <% end %>

Bài viết tham khảo:

http://railscasts.com/episodes/362-exporting-csv-and-excel

http://apidock.com/ruby/CSV