axlsxで作ったExcelファイルをそのままpaperclip経由でs3に保存する


Axlsxでレポート作成してs3に保存したい

Railsやっていたら管理画面とか作っているとレポートをExcelで出力してほしいと言われることがたくさんありますね。世の中Excelで動いてるんですよね。Excelはいろんな業務の糊のようなものですね。

バイナリデータをDBに突っ込むと、DBの容量を食うのと、DBのバックアップ時間が長くなるという問題があるので、やっぱり安定のAmazon s3に保存したいなと思ったのですが、一時ファイルを作らずにpaperclip経由でそのままアップロードしたいなと思ったのです。

ここに書かないこと

  • Railsでのpaperclipの設定方法など

やってみた。

モデル

モデルはReportモデルで、レポートの期間を指定するくらいです。

Reportモデル
# == Schema Information
#
# Table name: reports
#
#  id                   :integer          not null, primary key
#  start_date           :date             not null
#  end_date             :date             not null
#  content_file_name    :string
#  content_content_type :string
#  content_file_size    :integer
#  content_updated_at   :datetime
#  created_at           :datetime         not null
#  updated_at           :datetime         not null
#

class Report < ActiveRecord::Base
  has_attached_file :content
  validates_attached_content_type :content,
                                  content_type: %w(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
end

レポート生成するRake Task

report.rake
namespace :report do
  desc 'Create Report'
  task :create, "start_date", "end_date"
  task create: :environment do |x, args|
    unless args.start_date.present? && args.end_date.present?
      puts "Please input start_date and end_date."
      next
    end
    start_date = Date.parse(args.start_date)
    end_date = Date.parse(args.end_date)
    range = start_date.to_time..end_date.to_time.end_of_day
    Axlsx::Package.new do |p|
      wb = p.workbook
      default_style = wb.styles.add_style(font_name: 'MS Pゴシック', sz: 10)
      wb.add_worksheet(name: 'Sheet1') do |sheet|
        # レポートを作成する。サンプルなので適当
        Foo.in_range(range).find_each do |foo|
          row = [foo.name, foo.price]
          sheet.add_row row, style: default_style
        end
      end

      # ここからが本番
      file = Paperclip::StringioAdapter.new(StringIO.new(p.to_stream.read))
      file.original_filename = "report_#{start_date.strftime('%Y%m')}.xlsx"
      file.content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
      Report.create!(start_date: start_date,
                     end_date: end_date,
                     content: file)
    end
  end
end

すると、s3にExcelファイルが保存されました。やったね!

参考URL