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 %>