Config CarrierWave с Mongoid - GridFS
Я получаю проблемы, пытаясь использовать CarrierWave для загрузки API Rest API, разработанного в Rails 3, с базой данных MongoDB.
Я хотел бы сохранить некоторые файлы (не только изображения, но и файлы любого формата) с помощью системы MongoDB GridFS. Я прочитал много документов, которые рекомендуют мне использовать драгоценный камень CarrierWave.
Но у меня возникает ошибка при попытке настроить его.
Моя среда разработки: 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/ initializer / mongoid.rb):
Mongoid.load!("config/mongoid.yml")
- я могу без проблем выполнить команду "rails server" после последнего файла, config/initializers/carrierwave.rb:
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
2 ответа
Извините за медленный ответ. Во-первых, причина вашей ошибки в том, что Mongoid 3 больше не поддерживает Mongoid.database
, Теперь вы можете найти эти конфигурации в Mongoid::Config.sessions[:default]
объект.
НО ЭТО НЕ ЧТОБЫ ИСПРАВИТЬ ВАШУ ПРОБЛЕМУ! Mongoid 3 вообще не поддерживает GridFS. Из документов mongoid:
Нет поддержки GridFS
GridFS продается как основная функция базы данных, хотя на самом деле это не так. Это просто шаблон для хранения данных фрагментированного файла в виде документов в коллекции, как и любой другой документ. Реализация этого поведения осуществляется в драйверах клиента, а не в самой базовой базе данных, что может привести к несоответствиям в том, как это обрабатывается на> платформах.
Даже если такое поведение на клиенте приемлемо, его влияние на производительность приложения, когда вы не просто храните данные файла, довольно велико. Поскольку файлы хранятся в виде документов, они потребляют оперативную память точно так же, как любой другой документ в базе данных, и могут легко привести к максимальному потреблению памяти на вашем сервере. Существуют также ограничения по фрагментации данных, например, у вас нет возможности обновить файл - вы должны удалить файл и заменить его новым.
Учитывая это, мы не расставили приоритеты для какой-либо работы с GridFS на фронте, но есть жемчужина в конвейере для тех, кто может немного подождать, чтобы обновить. А пока у вас есть несколько вариантов...
Поэтому вместо того, чтобы искать другие способы хранения загрузок в GridFS за счет производительности, я бы предложил просто выбросить их в базу данных SQL. Если вы используете Mongo в качестве единственной базы данных, не откладывайте эту опцию. Не так сложно заставить ActiveRecord и Mongoid работать вместе. Но по моему опыту, загрузка бинарных объектов в любую базу данных может не работать хорошо. Я лично использовал бы файловую систему для хранения, с несущей волной или скрепкой, заботящейся об управлении. В качестве альтернативы, я бы предложил проверить несколько дешевых вариантов облачного хранения. Вы можете использовать что-то вроде aws-s3, отличный сервис. Он также имеет очень хорошо задокументированную совместимость с Carrierwave.
Если вы решили использовать GridFS, я бы посмотрел гем mongoid-grid_fs или некоторые альтернативные драйверы ruby MongoDB на веб-сайте 10gen.
Я впервые отвечаю на вопрос, поэтому надеюсь, что все делаю правильно.
Я боролся с той же проблемой при загрузке изображения с использованием несущей волны в моем приложении rails с Mongoid 3. Я считаю, что у меня есть решение (по крайней мере, оно работает локально на моем ноутбуке). Вот что я придумал:
Добавьте в свой gemfile кавалер-несущую- монгоид с веткой mongoid-3.0
, Этот драгоценный камень использует 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"
Надеюсь это поможет.