2 flat logo on transparent 256
2019-03-03

Carrierwave+S3で複数画像をアップロードする|Ruby on Rails5

2019 03 03 abstract business code 276452

Ruby on Rails4や5では簡単に画像アップロードできるgem Carrierwaveが用意されています。

このCarrierwaveを利用すれば画像とサーバーとの連携処理や一覧表示での方法などプログラミングに基本的な事が全て詰まっているので、プログラミング初心者や独学者はぜひチャレンジしてほしいです。

利用環境

Rails5.0

Ruby2.4.5

AWS S3

各種gemのインストール

carrierwaveは画像アップロード

fogはS3との接続

rmagickは画像のリサイズで利用します。

gem 'carrierwave'
gem 'fog'
gem 'rmagick'

インストールを実行

bundle install

なおrmagickをインストールする際はimage magickを利用しますが7系では動作しないので、注意が必要です。

詳細はrmagickのインストールには注意が必要|Ruby on Rails gem を御覧ください

アップローダーを生成

以下コマンドでアップローダーが生成されます

rails generate uploader Avatar

ファイルパスは以下

 app/uploaders/avatar_uploader.rb

Modelを生成

生成済みの場合はこちらは必要ありません。

rails generate model Picture name:string avatar:string

ファイル生成

class CreatePictures < ActiveRecord::Migration
  def change
    create_table :pictures do |t|
      t.string :name, :string
      t.string :avatar:, :string 
      t.timestamps null: false
    end
  end
end

コマンド実行

rails db:migrate

mount_uploaderを定義

PictureModelへmount_uploaderを定義します。 こちらはModelなのでご注意ください

class Picture < ActiveRecord::Base
  mount_uploader :avatar, ImageUploader
end

アップローダーの設定

アップローダーの各種設定を行います。

パス

app/uploaders/avatar_uploader.rb

コード例

class ImageUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

    storage :fog
  # 画像をリサイズする設定
  process resize_to_limit: [680, 300]

 #S3のアップロードディレクトリ
 #以下はバケッド名/picturesへアップロードする
  def store_dir
    "pictures"
  end

 #保存するファイルの種類を設定
  def extension_whitelist
    %w(png jpg jpeg pdf gif)
  end

 #ファイル名を指定今回はアップロード日時-ファイル名に設定
  def filename
    "#{Date.today}-#{original_filename}"
  end

end

アップロード先の指定

パス

config/initializers/carrierwave.rb

コード例

CarrierWave.configure do |config|
  config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: 'AWSアクセスキー',
      aws_secret_access_key: 'シークレットキー',
      region: 'ap-northeast-1'
  }

  # 公開・非公開の切り替え
  config.fog_public     = true
  # キャッシュの保存期間
  config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" }

  config.fog_directory  = 'S3バケット名'
  config.cache_storage = :fog

end

上記はキーを設定に直書きしていますが、設定的にenvファイルなどに記載するのが理想です。

詳細は Ruby on Railsの環境変数を管理できるGem dotenv-railsの紹介を御覧ください

Controllerの設定

コード例

class PicturesController < ApplicationController
  def index
    @pictures = Picture.all
  end

  def new
    @picture = Picture.new
  end

  def create
    picture_params[:avatar].each do |a|
      picture = Picture.new(picture_params.clone.merge({avatar: a}))
      picture.save
    end
    redirect_to dashboards_path
  end

  private
  def picture_params
    params.require(:picture).permit( :name, :photo, {avatar: []})
  end
end

今回は1回の処理で複数ファイルをアップロードできるように設定しています。

その為、createの処理でパラメーターの数だけ繰り返し処理を行います。

strong parameterで複数値を受け取る為、avatarは配列に設定します。

フォームを設定する

複数の画像登録ができるようmultiple: trueを設定

以下はnewフォーム(Slim) 詳細は【初心者・独学者向け】Ruby On Railsのviewを劇的に変える?!Slim入門

= form_for @picture, url: pictures_path do |f|

  = f.file_field :avatar_file_name, multiple: true
  = f.submit t('btn.submit')

フォーム登録とS3の連携が問題なければフォームで登録処理を実行した後に、コンソール上で以下のようなログが表示されます。

D, [2019-03-03T18:57:45.380054 #10019] DEBUG -- :   SQL (3.2ms)  INSERT INTO `pictures` (`created_at`, `updated_at`, `avatar`) VALUES ('2019-03-03 09:57:45', '2019-03-03 09:57:45', '2019-03-03-tableinfo25.png')
[fog][WARNING] fog: the specified s3 bucket name(hogehoge) contains a '.' so is not accessible over https as a virtual hosted bucket, which will negatively impact performance.  For details see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html
[fog][WARNING] fog: the specified s3 bucket name(hogehoge) contains a '.' so is not accessible over https as a virtual hosted bucket, which will negatively impact performance.  For details see: http://docs.amazonwebservices.com/AmazonS3/latest/dev/BucketRestrictions.html

その他関連記事

Ruby on Railsでto_paramメソッドを利用し、ルートへ文字列を追加する

Ruby on Railsで外部APIを利用して、簡単なアプリケーションを作成する

【初心者・独学者向け】Ruby on Railsで使いやすいメソッド.present?の紹介

Ruby On Railsで検索機能を実装する|ransack

Ruby on RailsでAction名やController名を取得する

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