Ruby
RubyOnRails

Rails4+MongoDB+Herokuでサイトのサムネイル画像を保存・参照する方法

More than 3 years have passed since last update.

概要

画像を生成するライブラリはいくつかありますが、調べた中で一番簡単に実装できた方法を紹介します。

前提として無料でサービスを公開できることを目指した結果、PaasはHeroku、画像はHerokuのMongoDB(最大50MB)にBinaryデータとして画像を保存することにしました。

他に候補としてAmazonS3などがありますが、アクセス数(転送データ量)に応じて従量課金されるので外しました。本格的にサービスを作るならS3やレンタルサーバなどを借りた方がいいかと思います。

構成

  • Ruby2.1.1
  • Rails4.0.4
  • MongoDB

Railsの実装

railsの基本的なアプリの作り方は省きます。Mongoidを使う上での注意点として、rails newするときにActiveRecordを含めないよう、-Oオプションを指定します。

Mongoid

Gemfileに以下を追加します。Rails4.xを使う場合、Mongoidも4.xを使う必要があります。現時点では4.0.0.beta1が最新なので、バージョンを指定します。また、Binaryオブジェクトを使うため、bsonとmopedも追加します。

gem 'mongoid', '4.0.0.beta1'
gem "bson"
gem "moped", github: "mongoid/moped"

参考:http://rubygems.org/gems/mongoid

Mongoidの4.xでMoped::BSONを使うために、config/application.rb に以下の記述を追加する必要があります。

require "bson"
require "moped"

Moped::BSON = BSON

参考:https://github.com/mongoid/mongoid/issues/3455

IMGKit

スクリーンショットを作成するためのライブラリはいくつかありますが、導入が簡単そうで、Herokuでも使用できることからIMGKitを使うことにします。

Mac上で使う場合は、wkhtmltoimageをダウンローとして/usr/local/binに置きます。(パスが通ればどこでもいいです。)

参考:http://weble.org/2012/06/01/mac-wkhtmltoimage
参考:https://github.com/csquared/IMGKit

画像の保存と参照

Modelのfieldには、type: Moped::BSON::Binary を指定します。これでBinaryデータが保存できます。

class Site
  include Mongoid::Document
  field :thumb, type: Moped::BSON::Binary
  ...
end

保存するためのControllerの処理は、以下のようにします。

def create
  img = IMGKit.new("http://example.com", quality: 50)
  site = Site.new
  site = Moped::BSON::Binary.new(img.to_img)
  site.save
  ...
end

参照は /img/(:id) のURLで取得したいので、以下のようにします。保存するfieldはthumbですが、取得するときはthumb.dataになることに注意してください。また、アクセスのたびにDBにアクセスするのは効率が悪いので、2回目以降はキャッシュを使うようにするといいと思います。

def img
  site = Site.find(params[:id])
  img = site.thumb.data if site.try(:thumb)
  send_data(img, filename: "#{site._id}.jpg", type: "image/jpeg", disposition: "inline")
end

参考:http://mongoid.org/en/mongoid/docs/documents.html
参考:https://github.com/csquared/IMGKit
参考:http://railsdoc.com/references/send_data

Herokuにデプロイする際の設定

Rails4

Rails3までと4では、設定が少し変わっていましたので、公式のドキュメントを参照しました。Gemfileに以下が必要となります。

ruby "2.1.1" # 使用するRubyのバージョン
gem 'rails_12factor', group: :production

参考:https://devcenter.heroku.com/articles/getting-started-with-rails4

Mongoid

config/mongoid.yml にproductionの設定を追加します。書き方はMongoid 3.xと同様で動きました。

production:
  sessions:
    default:
      uri: <%= ENV['MONGOHQ_URL'] %>

参考:https://devcenter.heroku.com/articles/mongohq#mongohq-replica-sets

IMGKit

./bin に wkhtmltoimage-amd64 を配置し、gitのリポジトリに追加します。

IMGKit.configure do |config|
  config.wkhtmltoimage = Rails.root.join('bin', 'wkhtmltoimage-amd64').to_s if ENV['RACK_ENV'] == 'production'
end

参考:https://github.com/csquared/IMGKit
参考:http://log.miraoto.com/2012/07/632/

日本語が化ける

heroku上でスクリーンショットを取ると、日本語の文字が正しく表示されません。これを防ぐには、fontファイルを/.fontsに配置してgitリポジトリに追加すればOKです。fontファイルはAPIフォントを利用しました。

参考:http://qiita.com/ssuzuki@github/items/58be855f909f29c05ae6
参考:http://d.hatena.ne.jp/shinichitomita/20120519/1337479457
参考:http://ipafont.ipa.go.jp/