使用Mongoid配置CarrierWave - GridFS

Flo*_*ild 0 mongodb gridfs mongoid carrierwave ruby-on-rails-3.2

我遇到了麻烦,尝试使用CarrierWave在Rails 3中开发的文件上传Rest API,使用MongoDB数据库.

我想要做的是使用MongoDB系统GridFS存储一些文件(不仅是图像,而且是每种文件格式).我阅读了许多建议我使用CarrierWave gem的文档.

但是当我尝试配置它时出错.

我的开发环境: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'
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

我用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
Run Code Online (Sandbox Code Playgroud)

并使用初始化程序(config/initializers/mongoid.rb)加载它:

Mongoid.load!("config/mongoid.yml")
Run Code Online (Sandbox Code Playgroud)

- 在最后一个文件config/initializers/carrierwave.rb之后,我可以毫无问题地执行"rails server"命令:

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
Run Code Online (Sandbox Code Playgroud)

然后在运行"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)
[...]
Run Code Online (Sandbox Code Playgroud)

我的文件模型定义如下:

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
Run Code Online (Sandbox Code Playgroud)

FileUploader只是CarrierWave上传器的扩展......

class FileUploader < CarrierWave::Uploader::Base
    storage :grid_fs
end
Run Code Online (Sandbox Code Playgroud)

dwa*_*ard 7

抱歉回复缓慢.首先,你的错误的原因是Mongoid 3不再支持Mongoid.database.您现在可以在Mongoid::Config.sessions[:default]对象中找到这些配置.

但这不是GONNA修复你的问题!Mongoid 3根本没有GridFS支持.来自mongoid文档:

没有GridFS支持

GridFS作为核心数据库功能销售,实际上并非如此.它只是一种模式,用于将分块文件数据作为文档存储在集合中,就像任何其他文档一样.此行为的实现在客户端驱动程序中处理,而不是在核心数据库本身中处理,这可能导致跨平台处理此行为的方式存在差异.

即使在客户端中具有此行为是可接受的,这对您不仅存储文件数据的应用程序性能的影响也非常大.由于文件存储为文档,因此它们就像使用数据库中的任何其他文档一样使用RAM,并且很容易导致服务器上的内存消耗最大化.在分块数据方面也存在一些限制,例如您无法更新文件 - 您必须删除该文件并将其替换为新文件.

鉴于此,我们没有在前面对GridFS的任何工作进行优先级排序,但是对于那些可以等待升级的人来说,还有一个宝石.在此期间,您有几个选择......

因此,我建议将它们放在SQL数据库中,而不是寻求以牺牲性能为代价在GridFS中存储上传的其他方法.如果您使用Mongo作为唯一的数据库,请不要被此选项拖延.让ActiveRecord和Mongoid并排工作并不是很困难.但根据我的经验,将二进制对象上传到任何数据库可能效果不佳.我个人会使用文件系统进行存储,使用carrierwave或paperclip来管理.或者,我建议查看一些廉价的云存储选项.你可以使用像aws-s3这样的优质服务.它还与Carrierwave有很好的兼容性.

如果您决定使用GridFS,我会查看mongoid-grid_fs gem或在10gen网站上查看一些替代ruby MongoDB驱动程序.


GTD*_*Dev 6

这是我第一次回答问题,所以我希望我做得对.

我在使用带有Mongoid 3的rails应用程序中使用载波上传图像时遇到了同样的问题.我相信我有一个解决方案(至少让它在我的笔记本电脑上本地工作.)这是我想出的:

使用分支将gemwave -mongoid gem 添加到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"
Run Code Online (Sandbox Code Playgroud)

制作载波的初始化器:

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

  config.storage = :grid_fs

  # Storage access url
  config.grid_fs_access_url = "/upload/grid"
end
Run Code Online (Sandbox Code Playgroud)

我知道我没有设置config.grid_fs_databaseconfig.grid_fs_host.这似乎在本地(在我的笔记本电脑上)工作我没有尝试使用远程gridfs数据库.

安装看起来很正常:

#app/models/user.rb
class User
  include Mongoid::Document
  mount_uploader :avatar, AvatarUploader
end
Run Code Online (Sandbox Code Playgroud)

上传者也是标准的:

#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
Run Code Online (Sandbox Code Playgroud)

为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
Run Code Online (Sandbox Code Playgroud)

并将路由添加到路由文件:

#config/routes.rb
match "/upload/grid/*path" => "gridfs#serve"
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.