0

Rails3で開発されたRestAPIをMongoDBデータベースでファイルアップロードするためにCarrierWaveを使用しようとすると、問題が発生します。

私がやりたいのは、MongoDBシステムGridFSでいくつかのファイル(画像だけでなくすべてのファイル形式)を保存することです。CarrierWavegemの使用を推奨する多くのドキュメントを読みました。

しかし、設定しようとするとエラーが発生します。

私の開発環境:Gemfile:

source 'https://rubygems.org'

gem 'rails', '3.2.8'

# MongoDB
gem 'mongoid', :git => 'git://github.com/mongoid/mongoid.git'
gem 'carrierwave', :git => "git://github.com/jnicklas/carrierwave.git"
# gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
gem 'mini_magick', :git => 'git://github.com/probablycorey/mini_magick.git'

gem 'bson_ext'
gem 'json'

application.rb:

require File.expand_path('../boot', __FILE__)

# ActiveRecord will not be use with MongoDB
# require 'rails/all'
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "rails/test_unit/railtie"
require "sprockets/railtie"
require "mongoid/railtie"
require "carrierwave"
# require "carrierwave/mongoid"

私はmongoid.yml(config / mongoid.yml)ファイルでデータベースを定義します:

development:
  sessions:
    default:
      database: lf_rest_api_development
      hosts:
        - localhost:27017
      options:
        consistency: :strong
  options:

test:
  sessions:
    default:
      database: lf_rest_api_test
      hosts:
        - localhost:27017
      options:
        consistency: :strong

そして、イニシャライザー(config / initializers / mongoid.rb)でロードします:

Mongoid.load!("config/mongoid.yml")

--最後のファイルconfig/initializers/carrierwave.rbの後で問題なく「railsserver」コマンドを実行できます。

CarrierWave.configure do |config|
    config.grid_fs_database = Mongoid.database.name
    config.grid_fs_host = Mongoid.config.master.connection.host
    config.storage = :grid_fs
    config.grid_fs_access_url = "/files"
end

そして、「rails server」コマンドを実行すると、次のエラーが発生します。

=> Booting WEBrick
=> Rails 3.2.8 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Exiting
/{API_path}/config/initializers/zcarrierwave.rb:4:in `block in <top (required)>': undefined method `database' for Mongoid:Module (NoMethodError)
[...]

私のファイルモデルは次のように定義されています:

require 'carrierwave/orm/mongoid'

class File
    include Mongoid::Document
    store_in_collection: "files", database: "lf_rest_api_developement", session: "default"

    key :filename, type: String
    key :content_type, type: String
    key :length, type: BigDecimal
    key :chunk_size, type: Integer, :default => 256
    key :upload_date, type: DateTime
    key :md5, type: String
    key :metadata, type: Array, :default => []

    mount_uploader :file, FileUploader

    index({ location: "2d" }, { min: -200, max: 200 })
end

FileUploaderは、CarrierWaveアップローダーの単なる拡張です...

class FileUploader < CarrierWave::Uploader::Base
    storage :grid_fs
end
4

2 に答える 2

7

応答が遅いのでごめんなさい。まず、エラーの理由は、Mongoid3がをサポートしなくなったことMongoid.databaseです。Mongoid::Config.sessions[:default]これで、これらの構成をオブジェクトで見つけることができます。

しかし、これはあなたの問題を解決するつもりはありません!Mongoid3はGridFSをまったくサポートしていません。mongoidドキュメントから:

GridFSサポートなし

GridFSは、実際にはそうではないのに、コアデータベース機能として販売されています。これは、他のドキュメントと同様に、チャンク化されたファイルデータをドキュメントとしてコレクションに格納するための単なるパターンです。この動作の実装は、コアデータベース自体ではなく、クライアントドライバーで処理されるため、プラットフォーム間での処理方法に不一致が生じる可能性があります。

クライアントでこの動作が許容できる場合でも、ファイルデータを保存するだけでなく、アプリケーションのパフォーマンスに与える影響は非常に大きくなります。ファイルはドキュメントとして保存されるため、データベース内の他のドキュメントと同じようにRAMを消費し、サーバーのメモリ消費を簡単に最大化する可能性があります。データのチャンク化には、ファイルを更新する機能がないなどの制限もあります。ファイルを削除して、新しいファイルに置き換える必要があります。

このため、GridFSを前面に置いた作業を優先しませんでしたが、アップグレードを少し待つことができる人のために、パイプラインに宝石があります。それまでの間、いくつかのオプションがあります...

したがって、パフォーマンスを犠牲にしてアップロードをGridFSに格納する他の方法を探すのではなく、SQLデータベースにアップロードすることをお勧めします。Mongoを唯一のデータベースとして使用している場合は、このオプションに躊躇しないでください。ActiveRecordとMongoidを並べて動作させることはそれほど難しくありません。しかし、私の経験から、バイナリオブジェクトをデータベースにアップロードするとうまく機能しない可能性があります。私は個人的にファイルシステムをストレージに使用し、carrierwaveまたはペーパークリップが管理を担当します。または、安価なクラウドストレージオプションを確認することをお勧めします。すばらしいサービスであるaws-s3のようなものを使用できます。また、Carrierwaveとの互換性についても十分に文書化されています。

GridFSを使用することにした場合は、mongoid-grid_fs gemを確認するか、10genWebサイトで代替のrubyMongoDBドライバーを確認します。

于 2012-10-25T19:30:34.563 に答える
6

質問に答えるのはこれが初めてなので、これが正しく行われていることを願っています。

Mongoid 3のRailsアプリケーションで搬送波を使用して画像をアップロードするのと同じ問題に苦労していました。解決策があると思います(少なくともラップトップでローカルに動作させることができます)。これが私が思いついたものです。

ブランチを使用して、 carrierwave-mongoidgemをgemfileに追加しますmongoid-3.0。このgemはmongoid-grid_fsを使用しています:

# Image Uploading
gem "carrierwave-mongoid", :git => "git://github.com/jnicklas/carrierwave-mongoid.git", :branch => "mongoid-3.0"

搬送波の初期化子を作成します。

#config/initializers/carrierwave.rb
CarrierWave.configure do |config|

  config.storage = :grid_fs

  # Storage access url
  config.grid_fs_access_url = "/upload/grid"
end

私は設定しなかったかを知っていconfig.grid_fs_databaseますconfig.grid_fs_host。これはローカルで(私のラップトップで)機能するようです。リモートのgridfsデータベースで試したことはありません。

取り付けは正常に見えます:

#app/models/user.rb
class User
  include Mongoid::Document
  mount_uploader :avatar, AvatarUploader
end

アップローダーも標準です:

#app/uploaders/avatar_uploader
class AvatarUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
  def store_dir
    "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  version :thumb do
    process :resize_to_limit => [200, 200]
  end
end

GridFSのコントローラーを作成します。

#app/controllers/gridfs_controller.rb
class GridfsController < ApplicationController

  def serve
    gridfs_path = env["PATH_INFO"].gsub("/upload/grid/", "")
    begin
      gridfs_file = Mongoid::GridFS[gridfs_path]
      self.response_body = gridfs_file.data
      self.content_type = gridfs_file.content_type
    rescue
      self.status = :file_not_found
      self.content_type = 'text/plain'
      self.response_body = ''
    end
  end
end

ルートをルートファイルに追加します。

#config/routes.rb
match "/upload/grid/*path" => "gridfs#serve"

お役に立てれば。

于 2012-12-01T23:13:17.617 に答える