CarrierWaveの導入
ここからは、RailsアプリケーションでCarrierWaveを使ってファイルアップロード機能を実装していきます。
インストール
GemfileにCarrierWaveを追記します。
…(中略)… gem 'carrierwave' …(中略)…
以下のコマンドを実行しCarrierWaveをインストールします。
bin/bundle
執筆時点では、1.2.3がインストールされました。
マイグレーション
articlesテーブルにimageカラムを追加するマイグレーションファイルを追加します。
bin/rails g migration add_image_to_articles image:string
生成されたマイグレーションファイルが以下のようになっていることを確認しておきましょう。
class AddImageToArticles < ActiveRecord::Migration[5.2] def change add_column :articles, :image, :string end end
マイグレーションファイルに問題がなければ、以下のコマンドを実行します。
bin/rails db:migrate
アップローダーの作成
CarrierWaveが提供するアップローダー用のクラスを作成するためのgenerateコマンドを、以下の通り実行します。
bin/rails g uploader image
▼
create app/uploaders/image_uploader.rb
生成されたアップローダークラスを確認すると、コメントを除いて以下のように定義されています。
class ImageUploader < CarrierWave::Uploader::Base …(中略)… storage :file …(中略)… def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end …(中略)… end
アップロードしたファイルをRailsサーバーに直接置く場合は、storageには:fileを指定します。S3などのクラウドストレージに置く場合は、:fogを指定します。
store_dirメソッドには、アップロードしたファイルパスの形式を指定します。デフォルトはpublic/uploadsディレクトリ配下に配置されます。
その他、コメントアウトされているアップローダーの、主な設定の役割を確認しておきます。
class FileUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: # include CarrierWave::RMagick # include CarrierWave::MiniMagick …(中略)…
ファイルアップロード時に画像リサイズ/変換するためには、CarrierWave::RMagickまたはCarrierWave::MiniMagickモジュールをインクルードする必要があります。これらのモジュールは、ImageMagickに依存します。有効にする場合は環境に応じてImageMagickを事前にインストールしておきましょう。OS Xであれば以下のコマンドでインストールできます。
brew install imagemagick
…(中略)… # Process files as they are uploaded: # process scale: [200, 300] …(中略)…
process scale: [横幅, 縦幅] とすることで、アップロード時に画像の横幅と縦幅を指定できます。
…(中略)… # Add a white list of extensions which are allowed to be uploaded. # For images you might use something like this: # def extension_whitelist # %w(jpg jpeg gif png) # end …(中略)…
extension_whitelistメソッドは、アップロードできる画像ファイルの種類を拡張子で指定して使います。リスト6のコメントアウトされているソースコードでは、アップロードファイルの拡張子がjpg、jpeg、gif、pngのいずれかでなければファイルをアップロードできないようにしています。
アップローダーをモデルにマウント
作成したアップローダーをArticleモデルにマウントし、使えるようにする設定を入れるため、以下のようにArticleモデルに追記します。
class Article < ApplicationRecord mount_uploader :image, ImageUploader …(中略)…
mount_uploaderはCarrierWaveが提供するDSLで、第1引数には、マイグレーションで追加した画像用のカラム名をシンボルで指定します。articlesテーブルにimageカラムを追加したので、ここでは:imageを指定しています。第2引数には、アップローダーのクラス名(ここではImageUploader)を指定します。
ビューファイルの修正
まず、フォームに画像パス用のフィールドを追加します。以下のように修正します。
…(中略)… <div class="field"> <%= form.label :body %> <%= form.text_area :body %> </div> <div class="field"> <%= form.label :image %> <%= form.file_field :image %> </div> …(中略)…
次に、アップロードした画像ファイルを表示するためのimage_tagヘルパーメソッドを以下のように追加します。
…(中略)… <p> <strong>Body:</strong> <%= @article.body %> </p> <p> <strong>Image:</strong> <%= image_tag @article.image.to_s %> </p> …(中略)…
マイグレーション時、articlesテーブルのimageカラムはString型で定義しましたが、アップローダーをマウントしたことで、@article.imageはImageUploaderクラスのインスタンスとなり、Stringクラスではありません。@article.image.to_sとすることで、image_tagの引数に画像パス(文字列)として指定できます。
コントローラーの修正
フォームに新たにfile_fieldを追加したので、Strong Parametersの設定に:imageを追加する必要があります。以下のようにArticlesコントローラーを修正します。
…(中略)… def article_params params.require(:article).permit(:title, :body, :image) end …(中略)…
動作確認
これでファイルアップロードの機能実装ができましたので、動作確認を行います。rails sコマンドでpumaサーバーを起動し「http://localhost:3000/articles」にアクセスして以下のように表示されることを確認します。
記事一覧から任意の記事詳細へのShowリンクをクリックして記事詳細を表示します。
Editリンクをクリックして記事編集画面を表示します。
[ファイルを選択]ボタンをクリックして、任意の画像ファイルを選択し、[Update Article]ボタンをクリックします。ここではRubyのロゴ画像をアップロードしました。