Skip to content

Instantly share code, notes, and snippets.

@mri-dula
Last active February 27, 2021 00:14
Show Gist options
  • Save mri-dula/cf81bd20d0b40ebbc87cde5c786bd0d4 to your computer and use it in GitHub Desktop.
Save mri-dula/cf81bd20d0b40ebbc87cde5c786bd0d4 to your computer and use it in GitHub Desktop.
Create active storage attachment records from paperclip files in PostgreSQL
class ConvertToActiveStorage < ActiveRecord::Migration[5.2]
require 'open-uri'
def change
active_storage_blob_statement = ActiveRecord::Base.connection.raw_connection.prepare('active_storage_blob_statement', <<-SQL)
INSERT INTO active_storage_blobs (
"key", filename, content_type, metadata, byte_size, checksum, created_at
) VALUES ($1, $2, $3, '{}', $4, $5, $6)
SQL
active_storage_attachment_statement = ActiveRecord::Base.connection.raw_connection.prepare('active_storage_attachment_statement', <<-SQL)
INSERT INTO active_storage_attachments (
name, record_type, record_id, blob_id, created_at
) VALUES ($1, $2, $3, #{"(SELECT max(id) from active_storage_blobs)"}, $4)
SQL
Rails.application.eager_load!
models = ActiveRecord::Base.descendants.reject(&:abstract_class?) - [Apartment::Adapters::AbstractAdapter::SeparateDbConnectionHandler]
transaction do
models.each do |model|
attachments = model.column_names.map do |c|
if c =~ /(.+)_file_name$/
$1
end
end.compact
if attachments.blank?
next
end
model.find_each.each do |instance|
attachments.each do |attachment|
if instance.send(attachment).exists? then
if instance.send(attachment).path.blank?
next
end
ActiveRecord::Base.connection.raw_connection.exec_prepared(
'active_storage_blob_statement', [
key(instance, attachment),
instance.send("#{attachment}_file_name"),
instance.send("#{attachment}_content_type"),
instance.send("#{attachment}_file_size"),
checksum(instance.send(attachment)),
instance.updated_at.iso8601
])
ActiveRecord::Base.connection.raw_connection.exec_prepared(
'active_storage_attachment_statement', [
attachment,
model.name,
instance.id,
instance.updated_at.iso8601,
])
end
end
end
end
end
ActiveRecord::Base.connection.execute('DEALLOCATE PREPARE active_storage_attachment_statement')
ActiveRecord::Base.connection.execute('DEALLOCATE PREPARE active_storage_blob_statement')
end
private
def key(instance, attachment)
SecureRandom.uuid
end
def checksum(attachment)
url = attachment.path
Digest::MD5.base64digest(File.read(url))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment