How to integrate Carrierwave into a Sinatra/ActiveRecord web app
I recently built a simple web application using Ruby built on the framework Sinatra. I called it “The Salted Hash” (a bit of code humor), a social food blog, where users can upload recipes and stories about the food they love!
This was a fun build, it was pretty straightforward…. UNTIL I got to the photo uploader, which was not exactly a walk in the park! Annnnd, what is a food blog without photos of delicious meals to entice readers!? So without further adieu, here is my intro to integrating Carrierwave into a Sinatra/ActiveRecord web app!
First up, what is it? Well, CarrierWave is a gem designed to allow users of your website to upload files such as photos, and store them on the server-side for later use. It is worth noting, that CarrierWave is capable of storing your data with services such as AWS instead of locally, but as this is an intro I will only show you how to store your files locally.
To get started, you will need to install the gem. I used a Gemfile for this project, so I added it there and use bundle to install with the rest of my gems.
gem 'carrierwave', '~> 2.0'
You will then need to require CarrierWave in your environment,
Note that this has to be after you require ActiveRecord. Also, note the code at line 19; this is defining the upload file’s root. I wanted to use my existing public folder as the root.
Next up, you need to build a model for your uploader. As I am using CarrierWave solely to upload photos, I called mine PhotoUploader:
Lets break this down. My PhotoUploader class inherits all sorts of useful bits from CarrierWave::Uploader::Base. The next line, storage :file, tells the app how to save the information that it will eventually be passed from the user's form. The store_dir, and cache_dir methods define where you would like store the files, and temporary files, inside the root that you defined in your environment file. The extension_whitelist method and content_type_whitelist method are defining which file types you are designating to be acceptable; in my case they are all common types of image files.
Now, for your database, you will need a column to store and associate the image. It is convention to call it an avatar, but of course you can call it whatever you'd like. Notice the data type is a string. Here’s a snippet of my schema:
At this point you should be able to create and store new instances of your uploader class manually via the terminal, so I will now show you how to upload a file via your form.
Because we are dealing with uploading a file, make sure that you put enctype=”multipart/form-data” inside of your form, which allows the form to pass the file through. I used a button to house the uploader. Note that my input has a type=”file”, which is also necessary to pass the file through to your controller.
Next, we instantiate a new Post object on creation, and associate the avatar with the photo that was passed in as params[:post][:photo].
This will store your photo in the directory that you specified above.
Finally, we get to show off all of our hard work! You can now evoke your stored image the same way you would show any other image, with an img tag!
And presto! We’ve got beautiful uploaded photos to brighten up the page!
For more detailed information on CarrierWave, please check out the docs at https://rubydoc.info/gems/carrierwave