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.
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.
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
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
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
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 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::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
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
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 = falseto
true, 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.