始めに...
CarrierWaveでユーザーアバターを実装したのですが、S3のパブリックアクセスを一部オフにしなければならなかったので最終的にActiveStorageを使用する方法に切り替えました。
ActiveStorageでの実装記事も作成したので比べてみてから取り掛かるといいかと思います。
【Rails】Devise、ActiveStorage、S3でユーザーアバターの実装
環境
Ruby: 2.7.1
Rails: 6.0.2.2
Devise導入済み
(gem 'devise', '~> 4.7', '>= 4.7.1')
手順
今回はカラム名を「avatar」で実装してますが好みでimageなどに変更できます。
Gemをインストール
gem 'carrierwave'
gem 'carrierwave-aws'
$ bundle install
Deviseにカラムを追加
class DeviseCreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
# avatarカラムの追加
t.string :avatar
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
# ~略~
end
Deviseのstrong parametersを追加
今回は編集画面でのみアバターを設定できるようにします。
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
# deviseのpermitted_parameterを追加する
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: [:avatar] )
# 登録時も必要であればsign_upを追加
# devise_parameter_sanitizer.permit(:sign_up, keys: [:avatar] )
end
end
uploaderファイルの作成
$ rails g uploader avatar
アンコメントアウトした部分のみ表示しています。
class AvatarUploader < CarrierWave::Uploader::Base
# 本番環境でのみawsへ保存される。
if Rails.env.production?
storage :aws
else
# 開発環境でテストする場合はこちらもawsに変更してください。
storage :file
end
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# 許可されるファイルの指定(pngなどの追加可)
def extension_whitelist
%w(jpg jpeg)
end
def filename
original_filename if original_filename
end
end
モデルの設定
「AvatarUploader」は先ほどのuploaderファイル名。
「:avatar」はカラム名。
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
# CarrierWaveで利用するUploader
mount_uploader :avatar, AvatarUploader
end
S3の設定
こちらの記事を参考に設定してください。
「パブリックアクセスの設定」は記事と同じ部分をオフにしないとエラーが起きます。
ブログの画像をamazon s3に保存する
Railsでaction text(active storage)の画像保存先をaws s3に変更した
CarrierWaveファイルの作成
「config/initializers」に「carrierwave.rb」ファイルを作成して次のコードを書き込んでください。
githubも見たけど作成コマンドは無さそうだったのでそれぞれ作成してください。
CarrierWave.configure do |config|
if Rails.env.production?
config.storage = :aws
config.aws_bucket = "バケット名"
config.aws_acl = 'public-read'
# The maximum period for authenticated_urls is only 7 days.
config.aws_authenticated_url_expiration = 60 * 60 * 24 * 7
# Set custom options such agit s cache control to leverage browser caching
config.aws_attributes = {
expires: 1.week.from_now.httpdate,
cache_control: 'max-age=604800'
}
# aws credential
# 次の項目は前項、S3の設定にある記事を参考にしてください
config.aws_credentials = {
access_key_id: Rails.application.credentials.dig(:aws, :access_key_id),
secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key),
region: 'ap-northeast-1'
}
else
# 本番環境以外はローカルにファイルを保存する
config.storage = :file
end
end
アバターの保存と表示
アバター保存画面
<%= form_with model: @user, url: user_registration_path, local: true do |f| %>
<div class="field">
<%= f.label :avatar %>
<%= f.file_field :avatar %>
</div>
<div class="actions">
<%= f.submit "保存" %>
</div>
<% end %>
アバター表示画面
<%= image_tag @user.image.to_s %>
後書き
実装方法を忘れないためにざっとまとめてみました。
しかし、概要でも書いたのですがActiveStorageのほうが何かと都合がよさそうなので今後CarrierWaveを使うことはないかもしれません。
参考
railsでcarrierwaveを使って画像をアップロード、表示
ブログの画像をamazon s3に保存する
Railsでaction text(active storage)の画像保存先をaws s3に変更した
carrierwave