CarrierWave/Mongoid/Herokuで作るRails画像アップロード機能

Rails 3.29/Heroku/Mongoid環境に画像アップロードの実装するために、「CarrierWave」を利用しました。その一連の流れを忘備録で書いておきます。

Demo
Source(GitHub)


CarrierWaveって何?

CarrierWaveは、シンプルで柔軟性の高いファイルアップロードアプリケーションです。
Ruby on RailsなどのRackベースのアプリケーションに組み込めます。

競合のGemとしては、「Paperclip」が挙げられます。現時点ではPaperclipのほうが人気は高いですが、扱いやすくて負けないくらい多機能です。

Mongoid + ImageMagickのインストール

もし、MacでMongoDBのインストールがまだの場合は、 MongodbをHomebrew/Mac Lionでインストール を良かったら見てください。

続いて、CarrierWaveを動かすために、ローカルテスト用にImageMagickをインストール(Mac Homebrewの場合)。

1
brew install ImageMagick

Rails プロジェクト作成

プロジェクトを作成する。今回はmongoidを利用するので、ActiveRecordをスキップ(-Oオプションを付ける)する。

1
rails new test-app --skip-test-unit -O

Gitリポジトリ作成を作成します。

1
2
3
Git init
Git add -A
Git commit -m "create new project"

Gemfileファイルに以下のGemを追加

1
2
3
4
5
6
7
8
9
10
11
12
13
ruby '1.9.3'
# Haml
gem 'haml-rails'
# Mongoid
gem 'mongoid'
gem 'bson_ext'
gem 'origin'
gem 'moped'
gem 'rmagick', :require => 'RMagick'
gem 'carrierwave'
gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'

Gemfileの設定を反映。

1
bundle install

mongoDBに接続するための設定を作成

1
rails generate mongoid:config

config/mongoid.ymlでProductionの設定をします。
こちらは後で使うHeroku アドオンMongoLab用の設定です。

1
2
production:
uri: <%= ENV['MONGOLAB_URI'] %>

Carrierwaveの設定

application.rbの更新。

1
2
3
4
5
CarrierWave.configure do |config|
config.storage = :grid_fs
config.grid_fs_connection = Mongoid.database
config.grid_fs_access_url = "/images"
end

アップローダ/Scaffoldの修正

アップローダのひな型の生成。

1
2
rails g scaffold article title:string
rails g uploader thumbnail

モデルファイル「app/model/article.rb」に以下を追加。

1
2
include Mongoid::Timestamps
mount_uploader :thumbnail, ThumbnailUploader

アップローダファイル「app/uploader/thumbnail_uploader.rb」の修正。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require "digest/md5"
class ThumbnailUploader &lt; CarrierWave::Uploader::Base
include CarrierWave::RMagick # コメントを解除
storage :grid_fs
def store_dir
"images/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :mini do
process :resize_to_limit => [200, 200]
end
end

コントローラファイル「add/controller/articles_controller.rb」の修正。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class ApplicationController < ActionController::Base
protect_from_forgery
def image
gridfs_path = env["PATH_INFO"].gsub("/images/", "")
begin
gridfs_file = Mongo::GridFileSystem.new(Mongoid.database).open(gridfs_path, 'r')
self.response_body = gridfs_file.read
self.content_type = gridfs_file.content_type
rescue
self.status = :file_not_found
self.content_type = 'text/plain'
self.response_body = ''
end
end
end

Viewファイル「app/views/articles/_form.html.haml」の修正。

1
2
3
= image_tag( @article.thumbnail_url ) if @article.thumbnail?
= f.file_field :thumbnail
= f.hidden_field :thumbnail_キャッシュ

Viewファイル「app/views/pages/show.html.haml」の修正。

vim app/views/pages/show.html.haml

1
= image_tag( @article.thumbnail_url(:mini))

routeファイルを修正。

1
2
root :to => "articles#index"
match "/images/uploads/*パス" => "application#image" #thumbnail画像

HerokuにPush

今回はHerokuとMongoDBのアドオン”MongoLab”を追加します。

1
2
3
git add -A
git commit -m "add scaffold/uploader"
heroku create test-app --stack cedar

MongoLabのAddonを追加。

1
Heroku addons:add mongolab:starter

結果をブラウザで確認。

補足

Mongoidは2.xx系と3.xx系でかなり設定方法が変更されています。
当初3.xx系で組み込みに挑戦しましたが、DBからのimage取得周りでどうしても手詰まりになり、
2.xx系を使った形にしています。技術力&知識がついたら3.xx系で再チャレンジしたいと思っています!

Special Thanks

herokuで無料のimage uploaderを作る

Rails3での画像アップロードの実装(ImageMagick + Rmagick + file_column)

[Rails] file_column から CarrierWave へ (序)

jnicklas / carrierwave GitHub

jnicklas / carrierwave-mongoid GitHub

テスト環境

# OS : Mac Lion(OS X 10.7)
# Rails : 3.2.9
# ImageMagic : 6.7.7-6.lion
# Gem Rmagick : 2.13.1
# Gem carrierwave : 0.6.2
# Gem mongoid : 2.4.12
# Gem carrierwave-mongoid : 0.2.1