CarrierWaveというライブラリを使うことで、簡単にRailsアプリに画像アップロード機能を付け加えることが出来る。
github.com
ここではCarrierWaveを使うための具体的な手順を書いていく。
動作確認はRuby 2.5.1、Ruby on Rails 5.2.1、macOS 10.13.6で行っている。
インストールとアップローダーの作成
まずはCarrierWaveをインストールする。
Gemfileにgem 'carrierwave'と追記して$ bundle installすれば、インストールされる。
すると、$ rails g uploader 作成するアップローダーの名前でアップローダーというクラスを作れるようになる。
今回は$ rails g uploader imageとした。
そうするとapp/uploaders/image_uploader.rbが生成される。
これが設定ファイルのような役割を果たすが、取り敢えずは何も手を加えずに進めることにする。
モデルの作成
今回は題材として画像掲示板のようなものを作ってみる。
Postというモデルがあり、投稿者を表現するnameと画像を表現するimageというカラムを持つ。データ型はどちらもstring。
早速モデルを作成する。マイグレーションも忘れずに行う。
$ rails g model Post name:string image:string $ rails db:migrate
最後にapp/models/post.rbを次のように書けば、モデルの作成は完了。
imageカラムに、先程作成したアップローダーを紐付けるような感じだろうか?
class Post < ApplicationRecord mount_uploader :image, ImageUploader end
たったこれだけで、画像を扱えるようになった。
あとは、画像だからといって特別なことは何も意識せず、Postモデルを使ってアプリを作ればいい。
コントローラーとフォームの作成
実際にアプリを作っていく。
まずconfig/routes.rbに以下を追記する。
get '/posts', to: 'posts#show' post '/posts/create', to: 'posts#create'
/postsでこれまでの投稿一覧を確認することができ、そこに設置してあるフォームに入力した内容を/posts/createにポストする。
次はコントローラー。
$ rails g controller Postsで作成した後、次のように書く。
class PostsController < ApplicationController def show @posts = Post.all end def create @post = Post.new(permit_params) @post.save! redirect_to action: 'show' end private def permit_params params.require(:post).permit(:name, :image) end end
画像アップロードなど意識していないことが分かる。
ただ単にフォームから送信されたものを受け取って保存しているだけで、特別な処理などない。
最後に、posts#showに対応したビュー、つまりapp/views/posts/show.html.erbを作成すれば完成。
<% @posts.each do |post| %> <p> <%= post.name %><br> <%= image_tag post.image.url %> </p> <% end %> <hr> <%= form_for :post, url: 'posts/create' do |f| %> <p><%=f.label "投稿者" %><br><%= f.text_field :name, placeholder: 'ハンドルネーム' %></p> <p><%=f.label "画像をアップロード" %><br><%= f.file_field :image %></p> <p><%= f.submit value: '投稿' %></p> <% end %>
4行目のpost.image.urlでアップロードされた画像のURLを取得できることと、10行目のファイル選択ボックスで対象のオブジェクトをimageにしていることがポイント。
ファイルを選択した上で投稿をクリックすると画像がアップロードされ、画面上に表示される。
アップロードされた画像はpublic/uploads/post/image/:postのID/ファイル名に保存される。
バリデーション
上述のようにapp/uploaders/image_uploader.rbを編集することで様々な設定を行うことが出来る。
例えば、ファイルサイズによるバリデーション。
以下の記述を追加すると、5MB以下の画像のみが許可されるようになる。
def size_range 1..5.megabytes end
それ以上のファイルをアップロードしようとすると以下のエラーメッセージが出る。
Validation failed: Image File size should be less than 5 MB
サムネイル
rmagickというライブラリを組み合わせることで、画像のリサイズも出来る。
github.com
早速Gemfileにgem 'rmagick'を追記して$ bundle installしようとしたが、エラーが出る。
自分の環境(macOS 10.13.6)だと、以下のエラーが出た。
An error occurred while installing rmagick (2.16.0), and Bundler cannot continue.
確認したところImageMagickが必要なようなので、Homebrewでインストールする。
$ brew install imagemagick@6 $ brew link --force imagemagick@6
その上で$ bundle installすると上手くいく。
続いてapp/uploaders/image_uploader.rbを編集していく。
画面上部の# include CarrierWave::RMagickのコメントアウトを外した上で、以下を書く。
version :thumb do process :resize_to_limit => [300, 300] end
これでアップロード時に、元画像とは別に300*300以内のサイズのサムネイル画像も保存されるようになる。
保存先は元画像と同じディレクトリで、thumb_アップロードした画像のファイル名という名前で保存される。
今回のデータ構造の場合、post.image.thumb.urlでアクセスできる。
<%= image_tag post.image.thumb.url %>