0

Xuất file CSV với rake task trong Rails

1. Bảng và dữ liệu

class Foo < ApplicationRecord
  has_many :bars 
end

class Bar < ApplicationRecord
  belongs_to :foo
end

Trong cơ sở dữ liệu có hai bản ghi trong bảng Foo:

  1. Named ‘East’, với Bar có 2 bản ghi ‘Tom’ and ‘Barb’.
  2. Named ‘Mountain’, với Bar có 3 bản ghi ‘Kurt’, ‘Marg’, and ‘Andy’

Từ đó, Sẽ có một tệp CSV giống như sau:

ID,Name,Bars
1,East, Tom Barb
2,Mountain, Kurt Marg Andy

2. Foo#to_csv

Foo#to_csv là hàm sẽ tạo tệp CSV từ tất cả các bản ghi trong bảng. Điều này có thể được gọi trên một phạm vi để chỉ xuất một tập hợp con của các bản ghi, hoặc cũng giống Foo.to_csv như sử dụng rake task để xuất ra.

class Foo
  ...
  def self.to_csv(options = {})
    CSV.generate(options) do |csv_file|
      csv_file << csv_header_row

      all.each do |foo|
        csv_file << foo.to_csv
      end
    end
  end

  def self.csv_header_row
    %w(ID Name Bars)
  end
end 

3. Foo.to_csv

Trong trường hợp này, Muốn trả về một mảng chứa khóa chính của bản ghi, tên của nó và danh sách tên của mỗi thanh của nó.

class Foo < ApplicationRecord
  def to_csv
    [id, name, bars.map(&:name).join(' ')]
  end
end

Điều này trả về một mảng chứa id, tên và một chuỗi chứa tên của mỗi has_many :bars quan hệ của bản ghi .

bars.map(&:name) lặp qua mỗi thanh và tạo một mảng từ kết quả của việc gọi tên trên mỗi bản ghi. .join(' ') lấy các tên đó và nối chúng lại với nhau thành một chuỗi duy nhất ngăn cách mỗi phần tử bằng một khoảng trắng.

4. Rake Task

Tạo rake task để xuất ra CSV đó. Để làm điều đó, bạn cần một tệp tại lib/tasks/export.rb.

Bên trong tệp đó, bạn nên thêm mã sau:

namespace :export do
  task foo: :environment do
    puts Foo.to_csv
  end
end

Đoạn mã trên sẽ tạo ra một tác vụ có thể được gọi qua rake export:foo . Điều này sẽ gọi Foo.to_csv và sau đó xuất file.

5. Xuất file

Để xuất dữ liệu ra tệp, chúng ta sẽ muốn sửa đổi tác vụ của mình để ghi kết quả đầu ra Foo.to_csv vào tệp.

namespace :export do
  task foo: :environment do
    file_name = 'exported_foo.csv'
    csv_data = Foo.to_csv

    File.write(file_name, csv_data)
  end
end

6. Định thời gian xuất file

Để định thời gian vào tên tệp đã xuất của bạn, hãy điều chỉnh file_name biến trông giống như sau:

time_stamp = Time.now.strftime('%Y%m%dT%H%M')
file_name = "#{exported_foo_#{time_stamp}.csv"

Thao tác này sẽ định sẵn thời gian vào các tệp đã xuất của bạn, cho phép bạn sắp xếp chúng dễ dàng hơn.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.