Image Upload with Carrierwave and Mongoid (GridFS – MongoDB) in Rails 3

Hello again, coders! Now I’m back with a topic to be discussed and it’s about Mongoid. Yap! Recently, I have a task that required me to upload images, but I have to use MongoDB as data management service. For uploader I chose Carrierwave and I use MongoDB’s feature to handle big files, that is GridFS. Actually, it’s not difficult to set all things up, but first you need to establish the mongoid service in your rails, you can refer it to my previous post. Now let’s get into the main topic.

Actually, I also refer to other article and I made some modification in the steps of doing it. These are the steps :

  1. Add new gems in your Gemfile :
    gem 'carrierwave', :git => "git://github.com/jnicklas/carrierwave.git"
    gem 'mini_magick', :git => 'git://github.com/probablycorey/mini_magick.git'
  2. Run bundle install command
  3. Add this code in your config/application.rb file
    require "mongoid/railtie"
  4. Now run this command : rails generate uploader image. This generator will generates a file in app/uploaders/image_uploader.rb. If the generator generates file named image.rb, please rename it with image_uploader.rb
  5. This is my settings in image_uploader.rb file :
    require 'carrierwave/processing/mini_magick'
    
    class ImageUploader < CarrierWave::Uploader::Base
      include CarrierWave::MiniMagick
    
      storage :grid_fs
    
      version :thumb do
        process :resize_to_fill => [80,80]
      end
    end
  6. Now let’s get into your model (in my case, the model is app/model/video.rb) and insert this code in the class :
    mount_uploader :image, ImageUploader

    :image is depend on your preference. If you prefer another name like avatar, profpic, etc you can change it. But, you need to have the same name with the uploader e.g. AvatarUploader, ProfpicUploader, etc. (CMIIW)

  7. Create a carrierwave config file in config/initializers/carrierwave.rb. The file’s containing these codes :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 = “/images” end
  8. Open your form file and put these code : (I use my file as an example)
     

    <%= form_for [:admins, @video], :html => {} do |f| %>
      <% if @video.errors.any? %>
        <div id="error_explanation">
          <h2><%= pluralize(@video.errors.count, "error") %> prohibited this content from being saved:</h2>
          <ul>
            <% @video.errors.full_messages.each do |msg| %>
              <li><%= msg %> <% end %> </li></ul>
        </div>
      <% end %>
    
      Video Name:
      <%= f.text_field :name %>
    
      Video Link:
      <%= f.text_field :link %>
    
      Video Thumbnail:
      <%= f.file_field :image %>
    
      Description:
      <%= f.text_field :description %>
    
      Category:
      <%
        collection = []
        @categories.each{|category|
         collection << [category.name, category.id]
        }
      %>
      <%= f.select :category_id, collection %>
    
    <%="f.submit"> <%= link_to 'Back', admins_videos_path %>
    <% end %>
  9. This is my index file :
     

    <%= notice %>
    <table>
    <tr>
      <th>Video Name</th>
      <th>Video</th>
      <th>Thumbnail</th>
      <th>Category</th>
      <th>Description</th>
      <th> </th>
    </tr>
    <% @videos.each{|video| %>
    <tr>
      <td><%= video.name %></td>
      <td><%= raw(video.link) %></td>
      <td>
      <% if video.image.url(:thumb).nil? %>
        <%= video.image.url(:thumb) %>
      <% else   %>
        <%= image_tag video.image.url(:thumb) %>
      <% end %>
      </td>
      <td><%= video.description %></td>
      <td><%= video.category.name %></td>
      <td><%= link_to 'Edit', edit_admins_video_path(video) %>
      <%= link_to 'Delete', {:controller => 'videos', :action => 'destroy', :id => video}, :method => :delete, :confirm => 'Are you sure?' %>
      </td>
    </tr>
    <% } %>
    </table>
    <%= link_to 'Add New Video', new_admins_video_path %>
  10. To make the image processing more quickly, create a file in app/controllers/gridfs_controller.rb which is containing these codes :
    require 'mongo'
    
    class GridfsController < ActionController::Metal
      def serve
        gridfs_path = env["PATH_INFO"].gsub("/images/", "")
        begin
          gridfs_file = Mongo::GridFileSystem.new(Mongoid.database).open(gridfs_path, 'r')
          self.response_body = gridfs_file.read
          self.content_type = gridfs_file.content_type
        rescue
          self.status = :file_not_found
          self.content_type = 'text/plain'
          self.response_body = ''
        end
      end
    end
  11. Next is put this code on your routes.rb file :
    match "/images/uploads/*path" => "gridfs#serve"

That’s all that I had done to establish carrierwave and mongoid by using GridFS as file repository. I hope this could help you.

Enjoy!

Advertisements

7 thoughts on “Image Upload with Carrierwave and Mongoid (GridFS – MongoDB) in Rails 3

  1. can you help me…I am developing a website where i have images on every web page I have use carrier wave and my SQL database i want to save the image name in the database and want to save all the images in public folder after that i need those images to be retrieve from that database and display on those webpages

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s