Webアプリで画像を扱う時、最近でこそcloudinaryの様な、簡単な画像編集までやってくれるサービスが出てきているものの、王道はImageMagick。
RubyではImageMagickを使うためにRMagickをgemで入れる必要があるが、ImageMagickのインストールの後ろには累々たる若葉マーク開発者の屍が多数、とまで行かないものの、多くの開発者の抜け毛を誘っている事は間違いないでしょう。
さて、私も導入します。
1.ImageMagickのインストール。
$ brew install imagemagick
==> Installing imagemagick dependency: pkg-config
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/pkg-config-0.27.1.lion.bottle.tar.gz
######################################################################## 100.0%
==> Pouring pkg-config-0.27.1.lion.bottle.tar.gz
/usr/local/Cellar/pkg-config/0.27.1: 9 files, 624K
==> Installing imagemagick dependency: jpeg
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/jpeg-8d.lion.bottle.tar.gz
######################################################################## 100.0%
==> Pouring jpeg-8d.lion.bottle.tar.gz
/usr/local/Cellar/jpeg/8d: 18 files, 1.3M
==> Installing imagemagick
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/imagemagick-6.7.7-6.lion.bottle.3.tar.gz
######################################################################## 100.0%
==> Pouring imagemagick-6.7.7-6.lion.bottle.3.tar.gz
==> Caveats
Some tools will complain unless the ghostscript fonts are installed to:
/usr/local/share/ghostscript/fonts
==> Summary
/usr/local/Cellar/imagemagick/6.7.7-6: 1405 files, 32M
あら、あっさり。
2.Sampleアプリ作成。
せっかくだから動かしましょう。
篳篥日記さんのこの記事を参考に。
$ rails new carrierwave_solo
3.Gemfileを編集して、Carrierwave導入
Gemfileに以下を追加。
gem 'rmagick'
gem 'carrierwave'
$ bundle install
Using carrierwave (0.7.1)
Installing rmagick (2.13.1) with native extensions
4.ScaffoldでUserを作成する。
$ rails g scaffold User name:string avatar:string
carrierwaveでは、画像保存カラムは、stringという決まりがあるらしい。
5.画像Uploadクラスimageを作成。
$ rails g upload image
Could not find generator upload.あれ?
$ rails g uploader image
create app/uploaders/image_uploader.rb
うまくいった。
6.app/uploader/image_uploader.rbを編集。
# encoding: utf-8
class ImageUploader < CarrierWave::Uploader::Base
#
include CarrierWave::RMagick
include Sprockets::Helpers::RailsHelper
include Sprockets::Helpers::IsolatedHelper
# Choose what kind of storage to use for this uploader:
storage :file
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Process files as they are uploaded:
process :resize_to_limit => [200, 200]
# Create different versions of your uploaded files:
version :thumb do
process :resize_to_fill => [50, 50]
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png)
end
end
7.app/uploader/avatar_uploader.rbを新規作成。
ImageUploaderクラスを継承する形で作成。
class AvatarUploader < ImageUploader
process :resize_to_fill => [100, 100]
version :thumb do
process :resize_to_fill => [50, 50]
end
end
8.ファイルサイズのvalidationを行う為の設定。
https://gist.github.com/1009861#file_file_size_validator.rb
ここを参考に、
8-1.lib/file_size_validator.rbファイルを作り、上記アドレスから内容を引っ張ってくる。
8-2.en.ymlにエラーメッセージの定義を追加する。(いずれja.ymlに移設しなければ)
8-3.application.rbに以下を追記。
config.autoload_paths += %W(#{config.root}/lib)
9.app/model/user.rbを編集。
class User < ActiveRecord::Base
attr_accessible :avatar, :name
mount_uploader :avatar, AvatarUploader
validates :name, presence: true
validates :avatar, file_size: { maximum: 50.kilobytes.to_i }
end
10.Viewを編集する。
10-1.app/views/shared/_errors.html.erbを作成。
<% if model.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(model.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% model.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
10-2.app/views/users/_form.html.erbを編集。
<%= form_for(@user) do |f| %>
<%= render partial: '/shared/errors', locals: { model: @user } %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :avatar %><br />
<%- if @user.avatar? -%>
<label><%= f.check_box :remove_avatar %>Remove</label>
<%= image_tag @user.avatar_url(:thumb).to_s %>
<%= f.hidden_field :avatar_cache if @user.avatar_cache %>
<%- end -%>
<%= f.file_field :avatar %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
10-3.app/views/users/show.html.erbを編集。
<p id="notice"><%= notice %></p>
<p>
<b>Name:</b>
<%= @user.name %>
</p>
<p>
<b>Avatar:</b>
<%= image_tag @user.avatar_url.to_s if @user.avatar? %>
</p>
<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>
10-4.app/views/users/index.html.erbを編集。
<h1>Listing users</h1>
<table>
<tr>
<th>Name</th>
<th>Avatar</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @users.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= image_tag user.avatar_url(:thumb).to_s if user.avatar? %></td>
<td><%= link_to 'Show', user %></td>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New User', new_user_path %>
11.migrate忘れとった
$ rake db:migrate
ひとまずUploadの動作確認は完了。
感想
・どうやらremove_avatarとavatar_cacheをエンティティに追加しないとダメっぽい。viewから該当項目を削除すると、問題なくuploadできるようになった。
・画像の比率を考えたリサイズ方法を確立しなければならない。Flickrとかどうやってんだろう。