読者です 読者をやめる 読者になる 読者になる

技術ネタとかの備忘録

最近の技術ネタとかの備忘録を書いていくブログです

Rails+MongoidでMongoDBに画像ファイルを保存する

今までHerokuで運用していたRailsアプリが、PostgreSQLの無料枠10,000レコードを超えるところだったので、PostgreSQLからMongoDBへ移行しました。

なんていったって、MongoDBのアドオンmLabは無料で500MBまで使い放題ですからね。 せっかくなのでMongoDB特有の機能を使おうと思い、画像ファイルをGridFSを使って保存しました。

バージョン

  • rails - 4.2.5
  • mongoid - 5.2.0
  • carrierwave-mongoid - 0.10.0
  • mini_magick - 4.6.1

使い方

CarrierWave::Uploader::Baseクラスを継承したUploaderクラスを作成します。

class ImageUploader < CarrierWave::Uploader::Base

  include CarrierWave::MiniMagick

  # :grid_fsを設定します。AWS S3に画像ファイルを保存する時は:fogを設定します。
  storage :grid_fs

  # 画像ファイルを120x120サイズへ変換して保存します。(サイズ変換が必要なければこの記述は不要です)
  process :resize_to_fill => [120, 120]

  # 画像ファイルにアクセスするためのURLのファイル名より前の部分になります。
  # ここでは"/users/image/1"な感じになります。
  def store_dir
    "/#{model.class.to_s.underscore.pluralize}/#{mounted_as}/#{model.id}"
  end

  # 画像ファイルがないときのURLになります。
  def default_url
    "/img/no-image.png"
  end

  # 許可する画像ファイルの拡張子になります。これ以外の拡張子の場合、バリデーションでエラーになります。
  def extension_white_list
    %w(jpg jpeg gif png)
  end

  # 画像ファイルにアクセスするためのURLのファイル名の部分になります。
  # ここでは"original.jpg"な感じになります。
  def filename
    "original.#{model.image.file.extension}" if original_filename
  end

end

Modelクラスにmount_uploaderを使って画像ファイルを保存するフィールドを追加します。 (ここではUserというModelクラスに追加します。)

class User

  include Mongoid::Document

  mount_uploader :image, ImageUploader

end

画像ファイルのURLのアクセス先を作成します。

ルーティングに画像ファイルのURLを追加します。

Rails.application.routes.draw do

  get "/users/image/:id/*path", to: "users#image"

end

ControllerクラスでMongoDBから画像ファイルを取得して返却します。

class UsersController < ApplicationController

  def image
    @user = User.find(params[:id])
    self.response_body = @user.image.read
    self.content_type = @user.image.content_type
  end

end

画像ファイルの表示は、image_urlメソッドで表示できます。

  = image_tag @user.image_url