Header
2019-10-07
2019-12-03

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

2019 10 08 b1a97d84f21fb13491980a099d30954e s

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

画像投稿用のコントローラーを設定

画像は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â  Ø°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:00p5dIEND®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を自動更新する

Ruby On Rails でデータを取得するメソッド一覧

【初心者・独学者向け】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:

Ruby単体でAPIを操作する|Udemy

Ruby、PHP、Python、Javaの予約語の一覧|そもそも予約語って何?

前の記事
次の記事
人気記事
カテゴリーから記事を探す