Gemを利用せずRailsで画像をDBに投稿する

Railsで画像を登録する際は
Carrierwave+S3で複数画像をアップロードする|Ruby on Rails5 などのCarrierwaveを利用する事が主流です。
ただ、簡単に設定したい場合もあると思うので、今回は直接画像をDBへ登録する方法を公開します
画像登録用のテーブルを生成する
マイグレーション ファイルは以下のような感じです 注意点は画像を保存するカラムは binaryで指定する
以下だと t.binary :imageの部分が該当
class CreateCompanyImages < ActiveRecord::Migration def change create_table :company_images do |t| t.string :filename t.binary :image t.timestamps end end end
binary はBlob型に変更されますが、最大容量が64kbです
画像添付で容量が足りない場合は画像が途中で切れてしまいます。
大容量の画像を添付する際は、以下のようにlimitなどで 最大容量を指定する必要があります
t.binary :image, limit: 1.megabyte
画像投稿用のコントローラーを設定
画像はRailsのActionDispatchで送付されてくる
params[:image][:image].readでバイナリ化されるので、
それを @image でインスタンス化したimageカラムに登録する
class CompanyImagesController < ApplicationController def create @image = CompanyImage.new @image.name = params[:image][:filename].original_filename @image.image = params[:image][:image].read @image.save! end end
投稿フォームの設定
new.html.erb
<%= form_for(@image) do |f| %> <div class="form-group"> <%= f.file_field :image %> <%= f.submit "投稿する" %> </div> <% end %>
※form_tagで設定する場合はmultipart trueにしないと、imageの値がstringで送信されるので注意
<%= form_tag({:controller => , :action => , :method => }, {:multipart => true }) %>
フォームから送信されるデータは以下のような感じActionDispatchで処理される
(byebug) params[:image][:image] #<ActionDispatch::Http::UploadedFile:0x0055d4c8ae18f0 @tempfile=#<Tempfile:/tmp/RackMultipart20191007-59-1s18085.jpg>, @original_filename="preview.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"image[image]\"; filename=\"preview.jpg\"\r\nContent-Type: image/jpeg\r\n">
コンソールでparams[:image][:image].readすると以下のような感じで、バイナリ化される
$ params[:image][:image].read PNG IHDR@# $ * gAMA± üa sRGB®Î é cHRMz&úèu0ê`: pºQ< bKGDÿÿÿ ½§ pHYs % % IR$ð ÄIDAThÞÍÉ$W ¿s ªÊÝ °Ý vÛ [,,Ù $ËjÀâ XXâ Xø ذc $Vl¼±1B 中略 5C þð~Ëݦï¬BÌ4ñ"º ¯^TáÑ©ãÇ/lQ<Ƚô÷ _Ü]òù^ ~{ ¸5o r.E 5¯NY§ ®øáó3J+§ºàßW_azC¡C %tEXtdate:create2019-10-08T15:35:47+09:00 h9Ø%tEXtdate:modify2019-10-08T15:35:47+09:00p5dIEND®B`
登録された画像を表示する
ルート
get 'company_images/show’ => 'company_images#show’, :as => :show_image
表示用ページ
show.html.erb
<%= image_tag(show_image_path(1)) %>
※showimagepath(1)の1の部分には表示したい画像IDなどが呼び出されるように設定
実運用は中間テーブルなどで、ユーザーと紐付けるなどが必要 詳細は以下
【初心者・独学者向け】Ruby on Railsで中間テーブルを作成し、多対多を実現する
コントローラー
send_dataでページに表示する
class CompanyImagesController < ApplicationController def show @image = CompanyImage. find(params[:id]) send_data @image.image, :type => 'image/jpeg', :disposition => 'inline' end end
注意点として、画像投稿フォームと画像表示ページは同じページ内では設定できないです
上記を同一のページに設定すると、ダブルレンダリングのエラーとなります。
その他関連記事
Ruby on Railsでsitemapを自動生成しsitemapを自動更新する
ITエンジニアに強い転職エージェント4選|現役エンジニアが解説
【初心者・独学者向け】Ruby on RailsでテーブルやModelを削除する際のコマンド
Rspecのエラー|ArgumentError is not a valid status
サーバーでNo space left on deviceが発生した場合の対処
can't find gem bundler (>= 0.a) with executable bundle (Gem: