heroku に画像をアップできるアプリケーションをデプロイしたとしても、アップした画像は数時間で消えるかデプロイするたびに消えてしまいます。
しかし、画像が消えるということを回避できる方法があります。
それは、画像をデータベースに格納するときにバイナリデータ
として保存する方法です。
ですが、この記事の方法は**「モックアップ用の簡易なアプリケーション」や「アクセスがなく自分しか使わないアプリケーション」**といったケースでやるのが好ましいです。
下記の注意点を読んでから、アプリケーションの状況に応じて実施を決断するようにしてください。
注意点
以下のサイトの回答者の方の答えが非常にわかりやすくて、画像をデータベースに保存するデメリット(とメリット)についてまとめられているので、参考にしてみてください。
データベースに画像を保存するのはありでしょうか? - teratail
テーブルを作成
今回は、既存のPostテーブル
に紐付けしたPhotoテーブル
のなかに画像を保存していくとします。
Postテーブル
とPhotoテーブル
の関係は、1対多です。
まずは、画像を保存するためのテーブルの作成から行います。
画像を保存するためのカラムは、bynary型
にします。
コンソールに下記のコマンドを打ち込み実行します。
$ rails g model Photo
そうすることで、マイグレーションファイルが生成されるので下記のように編集します。
class CreateUsers < ActiveRecord::Migration
def change
create_table : photos do |t|
t.bynary :image, nill: false
t.references :post, foreign_key: true, null: false
t.timestamps null: false
end
end
end
マイグレーションファイルを編集したら、下記のコマンドを実行してテーブルを作成しましょう。
$ rails db:migrate
作成した全てのテーブル情報は「schema.rb」ファイルでも確認することができます。
コントローラを編集
コントーラファイルには、「画像をデータベースに保存する」と「画像をデータベースから取り出す」といった2つの動きを追加していきます。
画像をデータベースに保存する
画像をデータベースに保存するには、read
というメソッドが重要になります。
「photos_controller.rb」ファイルを作成して、下記を追加します。
def create
@post = Post.new(post_params)
# バイナリ化した画像の呼び出し
params[:post][:photos_attributes]["0"][:image].each_with_index do |item, i|
if i != 0
@post.photos.build
end
@post.photos[i].image = item.read
end
end
private
def post_params
params.require(:post).permit(photos_attributes: [:image])
end
画像をデータベースから取り出す
画像をデータベースから取り出すには、send_data
というメソッドが重要です。
def send_img
tmpbin = Photo.find(params[:id])
send_data(tmpbin.image, :type => 'image/jpeg', :disposition => 'inline')
end
ビューを編集
ビューには、「画像のアップロード」と「画像の表示」とこれまた2つの動きを追加していきます。
画像のアップロード
画像をアップできるようにフォームを設置します。
<%= form_with model: @post, multipart: true do |f| %>
<%= f.field_for :photos do |i| %>
<%= i.file_field :image, type: :file %>
<% end %>
<%= f.submit "投稿する" %>
<% end %>
画像の表示
次に、データベースに保存した画像が表示されるように下記を追加します。
<% @post.photos.each do |photos| %>
<%= image_tag url_for(:controller => 'photos', :action => 'send_img', id => photos.id %>
<% end %>
ルートの設定を追加
最後の仕上げとして、「routes.rb」に下記を追加します。
get '/photos/send_img/:id', to: 'photos#send_img'
これでバイナリデータとした画像の保存から表示までを終わらせることができました。
heroku にデプロイするアプリケーションで画像投稿機能が付いているものでも、永続的に画像を表示させ続けられることでしょう!