LoginSignup
1
5

More than 3 years have passed since last update.

herokuにアップする画像を永続的に表示させる方法【Rails】

Posted at

heroku に画像をアップできるアプリケーションをデプロイしたとしても、アップした画像は数時間で消えるかデプロイするたびに消えてしまいます。
しかし、画像が消えるということを回避できる方法があります。

それは、画像をデータベースに格納するときにバイナリデータとして保存する方法です。

ですが、この記事の方法は「モックアップ用の簡易なアプリケーション」「アクセスがなく自分しか使わないアプリケーション」といったケースでやるのが好ましいです。
下記の注意点を読んでから、アプリケーションの状況に応じて実施を決断するようにしてください。

注意点

以下のサイトの回答者の方の答えが非常にわかりやすくて、画像をデータベースに保存するデメリット(とメリット)についてまとめられているので、参考にしてみてください。

データベースに画像を保存するのはありでしょうか? - teratail

テーブルを作成

今回は、既存のPostテーブルに紐付けしたPhotoテーブルのなかに画像を保存していくとします。
PostテーブルPhotoテーブルの関係は、1対多です。

まずは、画像を保存するためのテーブルの作成から行います。
画像を保存するためのカラムは、bynary型にします。
コンソールに下記のコマンドを打ち込み実行します。

$ rails g model Photo

そうすることで、マイグレーションファイルが生成されるので下記のように編集します。

xxxxxxxxxxxxxx_create_photos.rb
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」ファイルを作成して、下記を追加します。

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というメソッドが重要です。

photos_controller.rb
def send_img
  tmpbin = Photo.find(params[:id])
  send_data(tmpbin.image, :type => 'image/jpeg', :disposition => 'inline')
end

ビューを編集

ビューには、「画像のアップロード」と「画像の表示」とこれまた2つの動きを追加していきます。

画像のアップロード

画像をアップできるようにフォームを設置します。

new.html.erb
<%= form_with model: @post, multipart: true do |f| %>
  <%= f.field_for :photos do |i| %>
    <%= i.file_field :image, type: :file %>
  <% end %>

  <%= f.submit "投稿する" %>
<% end %>

画像の表示

次に、データベースに保存した画像が表示されるように下記を追加します。

index.html.erb
<% @post.photos.each do |photos| %>
  <%= image_tag url_for(:controller => 'photos', :action => 'send_img', id => photos.id %>
<% end %>

ルートの設定を追加

最後の仕上げとして、「routes.rb」に下記を追加します。

routes.rb
get '/photos/send_img/:id', to: 'photos#send_img'

これでバイナリデータとした画像の保存から表示までを終わらせることができました。
heroku にデプロイするアプリケーションで画像投稿機能が付いているものでも、永続的に画像を表示させ続けられることでしょう!

参考にさせてもらった記事

rails で画像ファイルを DB に保存する

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5