Recently I worked on a project where I had to upload a zip archive of images and then attach those images to Active Record
model objects on the Rails server.
- Note:
This example uses
Active Storage
to attach images toActive Record
objects.
Here is how I got it all working
Install Gem
Include this gem
gem 'rubyzip'
then do
bundle install
Unzipping and file attachment
We suppose an Active Record
model named Product
, which has an Active Storage
attribute called product_image
class OrderItem < ApplicationRecord
has_one_attached :product_image
end
The controller which renders a zip upload form in the action zip_upload_form
(view template code is not provided here) and the form gets posted to the zip_file
action, which then processes the zip file by calling the process_zip_file
method. It's better to put such code in a service but for the sake of this tutorial let's just put in the controller.
require 'zip'
class UnzipController < ApplicationController
# GET
def zip_upload_form
# this action renders form for zip file upload
end
# POST
def zip_file
# the form is posted to this action
# this action processes the uploaded zip file
# params[:zip] is the uploaded zip file
if params[:zip]
process_zip_file(params[:zip])
else
redirect_to zip_upload_form_path
end
end
private
def process_zip_file(tmpfile_zip)
Zip::File.open(tmpfile_zip.path) do |zipfile|
# iterating through all the entries found in the zip file
zipfile.each do |entry|
if entry.file?
puts "#{entry.name} is a file!"
attach_file_to_model_obj(entry)
elsif entry.directory?
puts "#{entry.name} is a directory!"
elsif entry.symlink?
puts "#{entry.name} is a symlink!"
end
end
end
end
def attach_file_to_model_obj(entry)
# first we create a temp file from the file found in the zip archive
# then attach the temp file to model obj
Tempfile.open(["my-filename", ".#{put_extension_here}"]) do |tmp|
# this line creates the temp file
entry.extract(tmp.path) { true }
# attaching the temp image file to active record object
Product.first
.product_image
.attach(io: File.open(tmp.path), filename: "my-filename.#{put_extension_here}")
end
end
end
Cover Image by JOHN TOWNER on Unsplash
Top comments (0)