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)
抱歉回复缓慢.首先,你的错误的原因是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驱动程序.
这是我第一次回答问题,所以我希望我做得对.
我在使用带有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_database或config.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)
希望这可以帮助.