Rails App
Phase Four
Now that the application looks pretty good (you did resize your browser to look at how it snaps at different sizes, right?), we can turn our attention back to the functionality of the application. We have a field for the picture, but right now it only is a text field. From a user’s perspective, this is pretty confusing. For our application, we want to give users the ability to upload an image file to our application.
File uploads can get pretty complex quickly, so it’s a good idea to look at what solutions exist. Two very popular methods for working with file uploads in Rails are CarrierWave and Paperclip. Each of these solutions does things slightly differently, and for completely arbitrary reasons, we’ll use CarrierWave in this application.
Libraries
The first thing we need to do is install the carrierwave
gem. Open
your Gemfile
in the text editor and add the this line to the top of the file, after the line including source 'https://rubygems.org'
:
Note: when you modify your gemfile you need to restart your server. Now that we’ve declared the dependency, we can install it with
bundler
.
When CarrierWave is installed, it includes new generators for rails
to
help us set up everything we need for the application. For our
application, we’re going to add a new uploader
named Picture.
Note If you ever want to see the generators that
rails
currently has access to, run thebin/rails generate
command.
Picture Uploader
We need to tell our Transcription
model that it should treat the field
we created (pictures
) through CarrierWave now. We need to edit
app/models/transcription.rb
and make it read as so:
Now we need to change the form for the transcription. We have to change
the form to allow multiple types of content (e.g. text from the form, as
well as a file) as well as change the picture
field to a file form
type.
Open the form partial (app/views/transcriptions/_form.html.erb
).
We need the form_for
line to read like this:
Now we need to change the field type of picture
from text_field
to
file_field
.
When you restart your server and add a new transcription, you should now see a form that looks like this:
Try uploading a file now! Does it work? Click around, is it doing what you expect?
Git
Ok, so the file uploads are functioning (which is different than working), so now is a good time to add and commit all of the new files we’ve created.
Show the Picture
Right now whenever we look at a view of the information (in the
transcription#index
and transcription#show
views), it simply
displays a string of the path to the image we’ve uploaded. Let’s change
that to show the image.
Let’s take care of the transcription#show
view first. Open
app/views/transcriptions/show.html.erb
and the line for the picture
.
We need to update it to read like this:
Now if you refresh your browser, does the image show up?
Hint: are you looking at the right page? A ‘show’ view only refers to a single item in the database.
Do we have access to any additional sizes of images (e.g. thumbnails)?
Generating Derivatives
To create thumbnails of the images (and provide smaller assets for
different views), we need to create different image files. CarrierWave
doesn’t do this directly, but provides access to two systems that do,
RMagick
and MiniMagick
. For CarrierWave, MiniMagick
is
recommended, so we’ll use that. This does require a system library named
imagemagick which is a Linux-based interface for working with image
files. First, let’s install imagemagick
with homebrew
. If you don’t have homebrew installed, download it here using the command line.
Now we need to add the mini_magick
gem to the Gemfile
. Remember: only lines that begin with $
are meant to be typed in the terminal.
And then install the gem.
Now we need to take a closer look at the uploader CarrierWave generated.
Open the app/uploaders/picture_uploader.rb
file.
There are a lot of lines commented out, and now we can uncomment some
that make sense for our app. We want to enable the MiniMagick
mixin,
process the files that are updated and create thumbnails, as well as
limit the type of images that can be uploaded (e.g. no TIFFs). These are
slight changes to the file, so read these carefully.
Now create a new transcription and add a new file. If you open the
public/uploads/
directory, you should see two files in the latest
created file. (If you have already uploaded photos, the number in the file path will change depending on the number of the photos uploaded. Second photo will be two, etc.)
Awesome, now we have access to the additional features from CarriewWave
to provide a thumbnail. We can use this in the transcriptions.index
view to show a thumbnail next to the title.
Open the app/views/transcriptions/index.html.erb
. We can then update
the view table to use the thumbnail. We’ll use the same picture_url
method, but pass the :thumb
symbol to retrieve the thumbnail version.
Start your server back up (if it’s not running) and see what happens. Are you seeing thumbnails for new items? What do you notice when you upload an image? Are you seeing thumbnails for older items? Why not?
Note: In development you may, from time-to-time, need to reset your database and clear out test data. The easiest way to do this is with the
bin/rake db:reset
command. NEVER DO THIS IN PRODUCTION!!!
Git
You may notice that there’s a directory public/uploads
that contains
your test data. We want to ignore these files (you don’t want to have
different files on the “real” server). For this, we’ll do some git
magick where we will include the parent directory (public/uploads
) and
ignore the child directories. This way we can upload as much test stuff
as we want, without accidently pushing our test data to the production
machine.
First we want to clear out the files that are in there and reset the database.
Next we need to add these directories to the .gitignore
file. Open the
.gitignore
file in your editor and add public/uploads/
(the trailing
slash is important). Here’s a fancy-smansy way to do it in the console:
Now we can add and commit the rest of the changed files for this feature.
Summary
In this module we added the abiilty for “users” to upload their own
images for transcriptions and then have the system resize them for us.
There is a fair amount of processing going on in the background to save
the various images. We also updated the view to use these new images,
and tried our hands at some git
-fu. The application is starting to
really come together now as a coherent application with expected user
interactions.
In the next module we’ll take a step back and work on sharing this code on Github and looking at workflow for managing these kinds of projects.
Questions
- How many images get written each time a user uploads an image?