Uploading multiple attachments with carrierwave/mongoid/nested_form
Recently I have met a requirement that need to upload multiple attachments to
a rails project. After some investigations, I choose carrierwave
finally.
Also, I selected nested_form
to manage uploading and deleting multiple
attachments.
Gemfile
First thing to use those gems is updating Gemfile
in the project, so those
lines have been added to the file:
# Mongoid
gem "mongoid"
# File upload
gem 'carrierwave'
gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
gem "mini_magick"
# Form for multi model
gem 'nested_form'
After the modification, remember to run bundle update
to update/install the
gems and dependencies.
Model
The next step is creating the models. For simplicity, there are only two
models in the project. One model named Foo
, which contains a title field and
a relationship field with the other model FooImage
. Here is the definition
of model Foo
.
class Foo
include Mongoid::Document
field :title, type: String
has_many :foo_images # Photoes of the dish
accepts_nested_attributes_for :foo_images, :allow_destroy => true
end
The accepts_nested_attributes_for
keyword enables saving associated records
though the parent, while the :allow_destroy
parameter allows deleting
associated though attributes hash.
Here comes the FooImage
model:
class FooImage
include Mongoid::Document
attr_accessible :image
mount_uploader :image, FooUploader
belongs_to :foo
end
This model only contains one field :image
, and the difference between others
is the mount_uploader
keyword, which is used to mount given uploader to the
given column, then assigning and reading from this field will upload and
retrieve files. The uploader is introduced by carrierwave
, which will be
introduced in next section.
Uploader
Uploader is used to handle the file uploaded to the server, which will save the file to specified location with multiple version. A uploader can be created by the command listed below:
rails g uploader Foo
A new uploader foo_uploader.rb
will be generated under directory
app/uploaders/
after command return. The uploader generated by default can
handle file uploading, and you can add some other function, such as scaling
image, set whitelisted extension, in the uploader. Remember to remove the
comment character from either CarrierWave::RMagick
or
CarrierWave::MiniMagick
line to enable scaling function. Carrierwave
alwo
support uploading file to cloud storage such as s3 directly, please refer to
the document for detail. In this uploader, I scale the uploaded image to
800x600
and add a thumbnail version with size 80x60
, here is the code:
process :resize_to_fill => [800, 600]
version :thumb do
process :resize_to_fill => [80, 60]
end
NOTICE: The generated uploader uses scale
for resizing, remember to replace it with existing function like resize_to_fill
.
Views
The last thing is the view. I plan to use two views in the project. Since this is just a simple demo, I have only created one record and shown the title and images with table.
By the way, if you want to deploy this application on production environment, please make sure those two configuration:
Make sure your web server, such as
Nginx
,Apache
, has write permission to its temp path. If you don’t know which directory is it, you can use this simple method to determine: First, check whether the production server can complete process of uploading attachment (Just uploading only, showing of image may have another problem which will be talked about below ). If there is no error, then the permission issue has already done. But if error occurred, please refer to the error log or access log of web server for tracing.Now the second problem, showing the image. After uploading successfully, you may can’t see the uploaded file. The problem is because production server do not serve static files. The quick fix for this is changing line
config.serve_static_assets = false
totrue
, but it is not the recommended way, since the production server can’t server static file efficiently. The better method is configuring web server to serve those static file directly, please refer to web server’s manual for detail.
So, that’s it. Thanks for reading, and here is the link of project on GitHub, any comments are appreciated.