目標:ユーザーのプロフィールに画像をアップロードして設定できるようにしたい
以下のGemをGemfileに記述します。

コンテナを再起動する
docker-compose stop docker-compose down docker-compose build
#アップローダーを生成する docker-compose exec web rails g uploader Image
userモデルに画像をアップロードするためにimageカラムを追加します。
docker-compose run web bundle exec rails g migration AddImageToUsers user image:string

マイグレートします
docker-compose run web bundle exec rake db:migrate
CarrierWaveを導入すると、Railsのジェネレーターで画像アップローダーが生成できるようになります。
user.rbに以下の記述を追加します。
mount_uploader :image, ImageUploader
users_controllerのストロングパラメーターに以下の記述を追加します。
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation, :image, :image_cache)
end
image_uploader.rbに以下の記述を追加
class ImageUploader < CarrierWave::Uploader::Base
# 画像サイズを取得するためにRMagick使用
include CarrierWave::RMagick
# このアップローダで使用するストレージの種類を選択します。
# developmentとtest以外はS3を使用
if Rails.env.development? || Rails.env.test?
storage :file
else
storage :fog
end
# アップロードされたファイルが保存されるディレクトリを上書きします。
# これは、マウントされることを前提としたアップローダのための、賢明なデフォルトです。
# 画像ごとに保存するディレクトリを変える
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# 許可する画像の拡張子
def extension_whitelist
%w(jpg jpeg gif png)
end
#画像の最大サイズを5MB未満にする
def size_range
1..5.megabytes
end
# 画像の上限を640x480にする
process :resize_to_limit => [640, 480]
# 保存形式をJPGにする
process :convert => 'jpg'
# サムネイルを生成する設定edit用
version :thumb do
process :resize_to_limit => [400, 400]
end
# ユーザー管理画面用
version :thumb100 do
process :resize_to_limit => [100, 100]
end
# 拡張子が同じでないとGIFをJPGとかにコンバートできないので、ファイル名を変更
def filename
super.chomp(File.extname(super)) + '.jpg' if original_filename.present?
end
# ファイル名を日付にするとタイミングのせいでサムネイル名がずれてエラーになるので
#ファイル名をランダムで一意にする
def filename
"#{secure_token}.#{file.extension}" if original_filename.present?
end
protected
def secure_token
var = :"@#{mounted_as}_secure_token"
model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
end
end
/app/views/users/new.html.erbに以下の記述を追加
<%= form_with model: @user, local: true do |f| %>
<%= image_tag @user.image.thumb.url if @user.image? %>
<%= render 'shared/error_messages', object: f.object %>
<div class="inputWithIcon">
<%= f.text_field :name, class: 'form-field', placeholder: 'Your name' %>
<%= f.email_field :email, class: 'form-field', placeholder: 'Email' %>
<%= f.password_field :password, class: 'form-field', placeholder: 'パスワード' %>
<%= f.password_field :password_confirmation, class: 'form-field', placeholder: 'パスワード確認' %>
</div>
<%= f.label :プロフィール画像をアップロードできます。 %>
<div class="file-upload_area">
<%= f.file_field :image, class: 'file-upload_input' %>
<%= f.hidden_field :image_cache %>
</div>
<div class="center-position">
<%= f.submit yield(:button_text), class: " btn float" %>
</div>
:image_cacheは
他の入力項目のバリデーションに引っかかった時、もう1回画像をアップロードしなくても良くなる
/app/views/users/show.html.erbの記述
<% @users.each do |user| %>
<%= user.name %>
<%= user.email %>
<% if user.image? %>
<%= image_tag user.image.thumb100.url %>
<% end %>
ユーザー管理画面に画像が反映されていればOK
編集画面app/views/users/edit.html.erbに以下の記述を追加
<%= user.text_field :name, class: 'form-field', placeholder: 'Your name' %>
<%= user.email_field :email, class: 'form-field', placeholder: 'Email' %>
<%= user.password_field :password, class: 'form-field', placeholder: 'パスワード' %>
<%= user.password_field :password_confirmation, class: 'form-field', placeholder: 'パスワード確認' %>
<%= user.label :プロフィール画像を変更できます。 %>
<div class="file-upload_area">
<%= user.file_field :image, class: 'file-upload_input' %>
</div>
<%= user.submit yield(:button_text), class: "btn float" %>
<% if logged_in? && !guest_user %>
<%= link_to "退会", @user, method: :delete,
data: { confirm: "本当に退会しますか?" } %>
<% end %>

ファイルを選択して編集できていればOKです!
/config/locales/carrierwave_ja.ymlに以下の記述を追加
ja:
errors:
messages:
record_invalid: 'バリデーションに失敗しました: %{errors}'
restrict_dependent_destroy:
has_one: "%{record}が存在しているので削除できません"
has_many: "%{record}が存在しているので削除できません"
carrierwave_processing_error: "処理できませんでした"
carrierwave_integrity_error: "は許可されていないファイルタイプです"
carrierwave_download_error: "はダウンロードできません"
extension_whitelist_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできるファイルタイプ: %{allowed_types}"
extension_blacklist_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできないファイルタイプ: %{prohibited_types}"
content_type_whitelist_error: "%{content_type}ファイルのアップロードは許可されていません"
content_type_blacklist_error: "%{content_type}ファイルのアップロードは許可されていません"
rmagick_processing_error: "rmagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}"
mini_magick_processing_error: "MiniMagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}"
min_size_error: "ファイルを%{min_size}以上のサイズにしてください"
max_size_error: "ファイルを%{max_size}未満のサイズにしてください"
date:
エラーが日本語で表示されたのを確認したらOKです!
