Migrations and helpers to move from Paperclip to ActiveStorage
To migrate the application as of April 2020: • leave models/screenshot.rb with “has_attached_file” • bundle exec rake db:migrate • bin/move_paperclip_to_activestorage • set models/screenshot.rb to “has_one_attached”
This commit is contained in:
parent
a0203d32af
commit
8adf682a0b
6 changed files with 239 additions and 0 deletions
|
|
@ -0,0 +1,27 @@
|
|||
# This migration comes from active_storage (originally 20170806125915)
|
||||
class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :active_storage_blobs do |t|
|
||||
t.string :key, null: false
|
||||
t.string :filename, null: false
|
||||
t.string :content_type
|
||||
t.text :metadata
|
||||
t.bigint :byte_size, null: false
|
||||
t.string :checksum, null: false
|
||||
t.datetime :created_at, null: false
|
||||
|
||||
t.index [ :key ], unique: true
|
||||
end
|
||||
|
||||
create_table :active_storage_attachments do |t|
|
||||
t.string :name, null: false
|
||||
t.references :record, null: false, polymorphic: true, index: false
|
||||
t.references :blob, null: false
|
||||
|
||||
t.datetime :created_at, null: false
|
||||
|
||||
t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true
|
||||
t.foreign_key :active_storage_blobs, column: :blob_id
|
||||
end
|
||||
end
|
||||
end
|
||||
105
db/migrate/20200413210200_convert_to_active_storage.rb
Normal file
105
db/migrate/20200413210200_convert_to_active_storage.rb
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
# Convert the screenshots from the deprecated Paperclip gem schema
|
||||
# to the new ActiveStorage schema built into Rails 5.2.
|
||||
|
||||
Dir[Rails.root.join("app/models/**/*.rb")].sort.each { |file| require file }
|
||||
|
||||
class ConvertToActiveStorage < ActiveRecord::Migration[5.2]
|
||||
require 'open-uri'
|
||||
|
||||
def up
|
||||
puts "Running up..."
|
||||
# postgres
|
||||
get_blob_id = 'LASTVAL()'
|
||||
# mysql / mariadb
|
||||
# get_blob_id = 'LAST_INSERT_ID()'
|
||||
# sqlite
|
||||
# get_blob_id = 'LAST_INSERT_ROWID()'
|
||||
|
||||
puts "Preparing queries"
|
||||
|
||||
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, #{get_blob_id}, $4)
|
||||
SQL
|
||||
|
||||
|
||||
Rails.application.eager_load!
|
||||
models = ActiveRecord::Base.descendants.reject(&:abstract_class?)
|
||||
|
||||
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|
|
||||
puts "Model: #{instance}"
|
||||
attachments.each do |attachment|
|
||||
puts "Attachment: #{attachment}"
|
||||
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
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def key(instance, attachment)
|
||||
SecureRandom.uuid
|
||||
# Alternatively:
|
||||
# filename = instance.send("#{attachment}_file_name")
|
||||
# klass = instance.class.table_name
|
||||
# id = instance.id
|
||||
# id_partition = ("%09d".freeze % id).scan(/\d{3}/).join("/".freeze)
|
||||
|
||||
# "#{klass}/#{attachment.pluralize}/#{id_partition}/original/#{filename}"
|
||||
end
|
||||
|
||||
def checksum(attachment)
|
||||
# local files stored on disk:
|
||||
url = attachment.path
|
||||
Digest::MD5.base64digest(File.read(url))
|
||||
|
||||
# remote files stored on another person's computer:
|
||||
# url = attachment.url
|
||||
# Digest::MD5.base64digest(Net::HTTP.get(URI(url)))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# This migration comes from active_storage (originally 20180723000244)
|
||||
class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0]
|
||||
def up
|
||||
return if foreign_key_exists?(:active_storage_attachments, column: :blob_id)
|
||||
|
||||
if table_exists?(:active_storage_blobs)
|
||||
add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue