Subscribed unsubscribe Subscribe Subscribe

at backyard

Color my life with the chaos of trouble.

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

Ruby Ruby on Rails 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

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

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