Rails - 从 Paperclip 迁移到 Active Storage

问题描述

正如标题所示,我正在尝试将 Rails 项目从 Paperclip 迁移到 Active Storage。

我不是实施 Paperclips 解决方案的开发人员,对它的工作原理知之甚少,我一直非常依赖下面链接的教程。

教程似乎说 rake 任务不能简单地从其他项目中复制和粘贴,因为它是附件路径的个人内容,并且完全掩盖了主题。我认为他们特指的是 key() 方法

我有 7 个模型需要映射到 Active Storage,我需要知道以下示例,我将如何编写 key

class Partner < ActiveRecord::Base


  has_attached_file :logo,url: "/assets/partners/logos/:id/:basename.:extension",path: ":rails_root/public/assets/partners/logos/:id/:basename.:extension"
  validates_attachment_content_type :logo,:content_type => ["image/jpg","image/jpeg","image/png","image/gif"]

 
end

这是我当前的 key() 方法(来自链接 #2)

def key(_instance,_attachment)
  # Get a new key
  SecureRandom.uuid
  # Alternatively:
  # instance.send("#{attachment}").path
end

1. RailsConf 2019 - How to migrate to Active Storage without losing your mind by Colleen Schnettler

2. Migrate a Rails Project from Paperclip to ActiveStorage

3. Active Storage Overview

如果有帮助,这里是完整的佣金任务

# lib/tasks/migrate_paperclip_data.rake
require 'open-uri'

namespace :migrate_paperclip do
  desc 'Migrate the paperclip data'
  task move_data: :environment do
    # Prepare the insert statements
    prepare_statements

    # Eager load the application so that all Models are available
    Rails.application.eager_load!

    # Get a list of all the models in the application
    models = ActiveRecord::Base.descendants.reject(&:abstract_class?)

    # Loop through all the models found
    models.each do |model|
      puts 'Checking Model [' + model.to_s + '] for Paperclip attachment columns ...'

      # If the model has a column or columns named *_file_name,# We are assuming this is a column added by Paperclip.
      # Store the name of the attachment(s) found (e.g. "avatar") in an array named attachments
      attachments = model.column_names.map do |c|
        Regexp.last_match(1) if c =~ /(.+)_file_name$/
      end.compact

      # If no Paperclip columns were found in this model,go to the next model
      if attachments.blank?
        puts '  No Paperclip attachment columns found for [' + model.to_s + '].'
        puts ''
        next
      end

      puts '  Paperclip attachment columns found for [' + model.to_s + ']: ' + attachments.to_s

      # Loop through the records of the model,and then through each attachment deFinition within the model
      model.find_each.each do |instance|
        attachments.each do |attachment|
          # If the model record doesn't have an uploaded attachment,skip to the next record
          next if instance.send(attachment).path.blank?

          # Otherwise,we will convert the Paperclip data to ActiveStorage records
          create_active_storage_records(instance,attachment,model)
        end
      end
      puts ''
    end
  end
end

private

def prepare_statements
  # Get the id of the last record inserted into active_storage_blobs
  # This will be used in the insert to active_storage_attachments
  # Postgres
  #get_blob_id = 'LASTVAL()'
  # mariadb
  # get_blob_id = 'LAST_INSERT_ID()'
  # sqlite
   get_blob_id = 'LAST_INSERT_ROWID()'

  # Prepare two insert statements for the new ActiveStorage tables
  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

  ActiveRecord::Base.connection.raw_connection.prepare('active_storage_attachment_statement',<<-sql)
    INSERT INTO active_storage_attachments (
      name,record_type,record_id,blob_id,#{get_blob_id},$4)
  sql
end

def create_active_storage_records(instance,model)
  puts '    Creating ActiveStorage records for [' +
           model.name + ' (ID: ' + instance.id.to_s + ')] ' +
           instance.send("#{attachment}_file_name") +
           ' (' + instance.send("#{attachment}_content_type") + ')'

  build_active_storage_blob(instance,attachment)
  build_active_storage_attachment(instance,model)
end

def build_active_storage_blob(instance,attachment)
  # Set the values for the new ActiveStorage records based on the data from Paperclip's fields
  # for active_storage_blobs
  created_at = instance.updated_at.iso8601
  blob_key = key(instance,attachment)
  filename = instance.send("#{attachment}_file_name")
  content_type = instance.send("#{attachment}_content_type")
  file_size = instance.send("#{attachment}_file_size")
  file_checksum = checksum(instance.send(attachment))

  blob_values = [blob_key,file_size,file_checksum,created_at]

  # Insert the converted blob record into active_storage_blobs
  insert_record('active_storage_blob_statement',blob_values)
end

def build_active_storage_attachment(instance,model)
  # Set the values for the new ActiveStorage records based on the data from Paperclip's fields
  # for active_storage_attachments
  created_at = instance.updated_at.iso8601
  blob_name = attachment
  record_type = model.name
  record_id = instance.id

  attachment_values = [blob_name,created_at]

  # Insert the converted attachment record into active_storage_attachments
  insert_record('active_storage_attachment_statement',attachment_values)
end

def insert_record(statement,values)
  ActiveRecord::Base.connection.raw_connection.exec_prepared(
      statement,values
  )
end

def key(_instance,_attachment)
  # Get a new key
  SecureRandom.uuid
  # Alternatively:
  # instance.send("#{attachment}").path
end

def checksum(attachment)
  # Get a checksum for the file (required for ActiveStorage)

  # local files stored on disk:
  # url = "#{Rails.root}/public/#{attachment.path}"
  # Digest::MD5.base64digest(File.read(url))

  # remote files stored on a cloud service:
  url = attachment.url
  Digest::MD5.base64digest(Net::HTTP.get(URI(url)))
end

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...