carrierwaveで画像投稿できるようにする
作ったもの
こちらのように商品などの投稿システムには欠かせない「画像投稿機能」を実装していきます。
Gemインストール
バージョンも指定しております。
mini_magickと本番環境でのアップロード用のfogも入れています。
Gemfile gem 'carrierwave', '1.2.2' gem 'mini_magick', '4.7.0' ・ ・ ・ group :production do (省略) gem 'fog', '1.42' end
bundle install
データモデルの設定
今回は実際に使っているProductモデルを例にします。
完成形のデータモデルは下記の通りです。
画像の情報はpictureカラムが持っています。
pictureカラムがなかったらrailsコマンドで作成
$ rails generate migration add_picture_to_product picture:string $ rails db:migrate
CarrierWaveでアップロードされた画像は、Productモデルのpicture属性と関連付けされているべきなので、そのためにmount_uploaderというメソッドを使います。属性名のシンボルと生成されたアップローダーのクラス名を取ります。
mount_uploader :picture, ProductPictureUploader
↑このように書かれます。
product.rbファイルに書いていきます。
app/models/product.rb class Product < ApplicationRecord (中略) validates :picture, presence: true ←画像なし無効化 mount_uploader :picture, ProductPictureUploader end
商品投稿なので画像なし避けるため、バリデーションも追加しています。
railsサーバーを一度再起動します。
フォームに画像を選択できるようにする
動画では画像選択フィールドでサムネが表示されてますが、その実装は長くなるのでまたの機会に笑
今回は無難にfile_fieldを追加します。
app/views/products/new.html.erb <%= form_for(@product) do|f| %> <%= render'shared/error_messages',object: f.object %> <div class="form-group"> <%= f.label "商品名" %> <%= f.text_field :name ,class: 'form-control' %> </div> <div class="form-group"> <%= f.label "定価" %> <%= f.text_field :price ,class: 'form-control' %> </div> (中略) * 画像の表示 #既存のフォームビューに追加 <span class="picture"> <%= f.file_field :picture %> </span> <% end %>
あとは投稿が成功していれば、表示させたいテンプレートにimage_tagを使えば表示させることができます。
自分が使っているテンプレートを例にすると
_product.html.erb <div class="item"> <%= image_tag @product.picture %> <p><%= @product.name %></p> </div>
@productにはProductのインスタンスが入っています。
このようにimage_tagのソースに@product.pictureとすれば表示させることができます。
本番環境での画像アップロード
本番環境ではクラウドストレージサービスに画像を保存するようにします。
先ほどインストールしたgemのfogを使うとクラウドストレージに保存することが簡単にできます。
設定は下記の通り
product_picture_uploader.rb class ProductPictureUploader < CarrierWave::Uploader::Base include CarrierWave::MiniMagick #開発環境ではローカルファイルに #本番ではクラウドストレージサービスを利用 if Rails.env.production? storage :fog else storage :file end ・ ・ ・ end
クラウドストレージサービスにはAmazon web ServiceのS3を使いました。
AWSの設定方法などはまた他の記事でかけたらと、、、
AWSでやることは
この3点ができたら、CarrierWaveの設定ファイルに画像の保存をS3を使うように設定していきます。
if Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { # Amazon S3用の設定 :provider => 'AWS', :region => ENV['S3_REGION'], # 例: 'ap-northeast-1' :aws_access_key_id => ENV['S3_ACCESS_KEY'], :aws_secret_access_key => ENV['S3_SECRET_KEY'] } config.fog_directory = ENV['S3_BUCKET'] end end
これは情報漏洩を防ぐために、環境変数を使用しています。
Herokuを使っている場合は、下記のように環境変数の設定をしましょう。
$ heroku config:set S3_ACCESS_KEY="Accessキー" $ heroku config:set S3_SECRET_KEY="Secretキー" $ heroku config:set S3_BUCKET="Bucketの名前" $ heroku config:set S3_REGION="Regionの名前"
これで設定は完了!
最後に画像を保存するディレクトリをGitへの保存対象から外します。
.gitignore . . . # アップロードされたテスト画像を無視する /public/uploads
気づいたことがあれば、そのつど追記します。