at backyard

Color my life with the chaos of trouble.

rubyzipを使ってzip圧縮を実装する。

Rubyスクリプト内での実装。

rubyzipを使ってZIP圧縮を書いたのだが、
単純なZIP圧縮処理を書くところで思いがけず時間をかけてしまったので、
自身への振り返りとして備忘録がてら圧縮処理を書いていく。

基本的に、Githubリポジトリ内の"Usage"を参考にしている。

github.com


下記を書いてbundle install。

gem 'rubyzip'

コードは下記の通りでrequireしてから実装していく

require 'zip'
  def self.create_zip_archive

    # カレントディレクトリ配下にある"zip_target"内のファイルをZIPにまとめる
    # カレントディレクトリ配下にある"output"ディレクトリ内に現在の日付時刻のzipファイルを作成する
    target_files_path = "#{Dir::pwd}/zip_target"
    file_name = Time.now.strftime("%Y%m%d-%H%M.zip")
    output_zip_path = "#{Dir::pwd}/output/#{file_name}"

    # "zip_target"内のファイル名をArrayクラスに格納していく
    target_files = []
    Dir.glob("#{target_files_path}/*.*").each do |i|
      target_files.push(File.basename(i))
    end

    # zip archiveを作成する
    Zip::File.open(output_zip_path, Zip::File::CREATE) do |zipfile|
      target_files.each do |file|
        zipfile.add(file, "#{target_files_path}/#{file}")
      end
    end
  end

Ruby on Railsでの実装

DBから取得した投稿データ(postdata)を、
StringIOを使ってテキストファイルに書き込み、
そのファイルをZIP圧縮処理して、
"output"配下にエクスポートするという流れ。

ちなみにRailsのVersionは5を使用している。

Controllerでの処理。

対応するユーザIDの投稿データをDBから取得して、
それらのデータをまとめてZIP圧縮しようとしている。
実際のZIP圧縮処理はModel内に記載。

 def export_zip
    postdata = Post.where(user_id: params[:id])
    Post.export_zip_archive(postdata)
    render :export_zip
  end

Modelでの処理。
こちらで実際にZIP圧縮を行っている。

require 'zip'
require 'stringio'


  def self.export_zip_archive(postdata)

    buf = StringIO.new

    # DBから取得したデータを書き込む
    postdata.each do |i|
      buf.puts(i.id)
      buf.puts(i.content)
      buf.puts(i.user_id)
      buf.puts(i.created_at)
      buf.puts(i.updated_at)
      buf.puts("\n")
    end

    filename = Time.now.strftime("%Y%m%d-%H%M")

    output_zip_path = "#{Rails.root}/output"
    FileUtils.mkdir_p(output_zip_path) unless FileTest.exist?(output_zip_path)

    # テキストファイルに書き込む
    file_name = "#{output_zip_path}/#{filename}.txt"
    File.open(file_name, "w") do |i|
      i.puts(buf.string)
    end

    # 書き込んだテキストファイルを対象にZIP圧縮処理を行う
    Zip::File.open("#{output_zip_path}/#{filename}.zip", Zip::File::CREATE) do |zipfile|
      zipfile.add(File.basename(file_name), file_name)
    end

 # テキストファイルは削除する
    FileUtils.rm(file_name)

  end

初心者感あふれる実装だと書いたものを見返してみて思う。
もう少しスマートに、そしてスピード感を持って実装を行っていきたいと思う、今日この頃。

ちょっと時間が経ってから、見返してリファクタリングしよう。