LoginSignup
7
3

More than 3 years have passed since last update.

PaperclipからActiveStorageに移行する(AWS)

Last updated at Posted at 2019-09-28

PaperclipでAWS上にデータを保管していましたが、Rails5.2から追加されたActiveStorageの利用を推奨として、Paperclipがdeprecatedになったため、ActiveStorageへの移行を行うことにしました。

Paperclip内の移行手順のドキュメントに従うことで基本的にはスムーズに移行できますが、英語が完璧でなかったり細かいイレギュラーな部分でつまずいたので、備忘録として残しておきます。

作業順

  1. ActiveStorageのインストールとストレージの設定
  2. mini_magickのgem追加
  3. paperclipのgemを外す
  4. モデルにActiveStorageの設定をする
  5. 元データをActiveStorageのレコードに再登録する ★
  6. Viewの更新
  7. default_url対応 ★

重点はこの★のところだけです。あとは、ドキュメントどおりなので割愛。

ActiveStorageにデータを移行する

上記作業順の1,2,3まで終わったら、モデルにActiveStorageの設定をします。

User.rb
    has_one_attached :photo

元データからActiveStorageのレコードに再登録する

rakeタスクで、元データを一つずつ順番にActiveStorageデータとして再登録します。
この作業の良い点

  • development環境からできる。
  • 元データを一旦残した状態にしておける。(最悪問題があった場合に救出できる)

一つのデータあたりにかかる時間は画像サイズにもよりますが、平均1,2秒程度でした。移行したいもののデータ量によっては、実行するタイミングを考えた方が良さそうです。

paperclipの移行ドキュメントに掲載されているrakeタスクからの変更点は以下のとおりです。

  • ファイル名に日本語URLが含まれている場合の対応
  • ファイルがなぜかなくなっていてエラーが出たので、ファイルが開けない場合の対応

※また私の場合、photoの親モデルであるUserモデルのコールバックが悪さをしてつまずきました。このタスクは一回しか走らせないので、いらないコールバックはコメントアウトしておくと安全かも。

lib/tasks/users.rake
namespace :users do
  desc 'Migrate paperclip to ActiveStorage'
  task migrate_to_active_storage: :environment do
    User.where.not(photo_file_name: nil).find_each do |user|
       # 移行前のオリジナルファイル名を参照
      image = user.photo_file_name
      # 以下の一行はpaperclipの移行ドキュメントにはありましたが、URLパターンによっては不要
      # ext = File.extname(image) 

      # 移行前のURLパターン
      image_original = CGI.unescape("#{user.id}_#{image}")

      # 移行前URLのフルパス
      # URI.encodeで日本語や記号を含むファイル名に対応
      photo_url = URI.encode "https://s3.amazonaws.com/hogehoge/photos/original/#{image_original}"

      # open()で何らかの理由でファイルが開けなかった場合にエラーを返す
      begin
        uri = open(photo_url)
      rescue => e
        p "ERROR: #{e}"
      end
      p "URL #{photo_url} e? #{e.blank?}"

      # ファイルが正しく開けたら、ActiveStorageで保存
      user.photo.attach(io: open(uri),
        filename: user.photo_file_name,
        content_type: user.photo_content_type) if e.blank?
    end
  end
end

上記のrakeタスクを実行。

$ rake users:migrate_to_active_storage

mini_magickの追加

ドキュメント内にそっと書かれていた、mini_magickを追加してねという一文をスルーしてしまったために、この流れの最後までやって試したときに、以下のようなエラーが出ました。

LoadError (cannot load such file -- mini_magick)

どのタイミングでも良いので、mini_magickを入れましょう。

gem 'mini_magick'

paperclipのdefault_url・・・

paperclipのdefault_url設定の良い移行の仕方を探していたのですが、ActiveStorageではその機能はない模様。
decoratorやhelperメソッドでカバーするしかなさそうです。

私の場合は、Userのアバターがない場合の表示をするのに、decoratorで対応しました。(gem active_decorator)

user_decorator.rb
module User
  def avatar(size='mini')
    px =
      case size
        when 'mini' then MINI
        when 'thumb' then THUMB
        when 'small' then SMALL
        else MINI
      end
      # MINI,THUMB,SMALLの定数はconfig/initializers/constants.rbにまとめて持っている

    if self.photo.present?
      image_tag(self.photo.variant(resize: "#{px}x#{px}"), class: 'avatar')
    else
      # webpackerで画像を管理。cssで画像サイズを調整。
      image_pack_tag("noimage.png", class: "avatar #{size}")
    end
  end
end
7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3