使用したgem
・carrierwave ファイルをアップロードする機能 github.com
・mini-magick 画像加工する機能 github.com
工程
1. carrierwaveとmini-magickをbundle install
#Gemfileに以下を追記し、bundle install gem 'carrierwave', '~> 2.0' gem 'mini_magick', '~> 4.8'
2. uploaderを作成
rails generate uploader 任意のファイル名
3. uploaderファイルに以下を設定
# class ファイル名+Uploader < CarrierWave::Uploader::Base # アップロードしたファイルはpublic/配下に保存 storage :file # public/配下のディレクトリの設定 def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end # 画像がなかった時のdefault画像の設定 def default_url(*args) 'board_placeholder.png' end # アップロードするファイルの拡張子を指定 def extension_whitelist %w(jpg jpeg gif png) end
4. カラムに画像を追加
$ rails g migration add_ファイル名_to_テーブル名 カラム名:stirng $ rails db:migrate
データベースサーバーの要領が圧迫されるため、カラムには「DBに保存されている画像ファイル名」が保存される。
画像を表示する時は「画像の保存してある場所を示すpath」と
「DBに保存されている画像ファイル名」を使用して表示させる。
参考:pikawaka.com
5. form_withタグをviewファイルに記載
# <%= form_with model: モデル名, local: true do |f| %> <%= f.label :カラム名 %> <%= f.file_field :カラム名 %> <%= f.hidden_field :カラム名_cache %> # <%= f.submit %> # <% end %>
6. controllerのstrongパラメータを画像データを入力できるように設定
def 〇〇_params params.require(:モデル名).permit(:カラム名, :カラム名, :画像カラム名, :画像カラム名_cache) end
cacheとは?
Making uploads work across form redisplays
Often you'll notice that uploaded files disappear when a validation fails.
CarrierWave has a feature that makes it easy to remember the uploaded file even in that case.
Suppose your user model has an uploader mounted on avatar file, just add a hidden field called avatar_cache (don't forget to add it to the attr_accessible list as necessary).
- 公式documentより
検証が失敗すると、アップロードされたファイルが消えるため、
CarrierWaveにはその場合でもアップロードしたファイルを記録する機能があります。
カラム名_cacheという非表示フィールドを追加することで実装できます(必要に応じてattr_accessibleリストに追加すること)。
7. 出力対象の部分テンプレートに入力
# 部分テンプレートの画像挿入部分 # render @インスタンスのコレクション(例:@インスタンス名+s)で呼び出されている前提 <%= image_tag ローカル変数.カラム名_url, size: '〇〇x〇〇' %>
8. .gitignoreにpublic/uploadsを追記
.ignoreにpublic/uploadsを追記することで、ローカルでアップロードされたファイルをgit管理下から外すことができる。
# .gitignore public/uploads
詳しくはこちらを参照 【IT用語】.gitignoreの書き方を図解形式で理解しよう! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト
選択した画像をプレビュー表示にする
1. 上記5で定義したf.file_fieldを以下に変更する。
# _form.html.erb(new.html.erbで # <%= render 'form', { a: @b} %>を定義した場合 # a = 部分テンプレート内で使用する変数 # b = 変数にいれる値(controllerやviewで定義した変数名) <%= f.file_field :カラム名, onchange: 'previewImage()', accept: 'image/*' %> <%= image_tag 変数a.カラム名.url, id: 'preview', size: '〇〇x〇〇' %>
・onchange:change イベントを処理する EventHandler 。入力欄や選択肢が変更された時に発生。
onchangeについて→GlobalEventHandlers.onchange - Web API | MDN
JavaScriptのonchangeの使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
・acceptオプション:フォームで受付可能なMIMEタイプを指定
acceptオプションについて→フォーム(form) | Railsドキュメント
MIMEタイプについて→MIME タイプ (IANA メディアタイプ) - HTTP | MDN
2. assets/javascript/common.jsに以下を記載
function previewImage() { const target = this.event.target; const file = target.files[0]; const reader = new FileReader(); reader.onloadend = function () { const preview = document.querySelector("#preview") if(preview) { preview.src = reader.result; } } if (file) { reader.readAsDataURL(file); } }
FileReader オブジェクト:ユーザーのコンピュータに保存されているファイル (または生データ バッファ) の内容を非同期に読み取る。
FileまたはBlob オブジェクトを使用して、読み込むファイルまたはデータを指定します。
→FileReader - Web API | MDN