If you’ve read any articles I’ve published before this one was published, you’ll notice that in addition to my tendency to over explain and ramble a bit, they are pretty sparse in terms of pictures, pretty or not. In fact, as of this date (May 31, 2016), there are no images uploaded on my website, mostly because I haven’t implemented any functionality to be able to place them on the website, either through standard ruby on rails, or through the markdown functionality currently used to write these articles.
As previously stated, the functionality in this web site is all built by me, without any blogging platform functionality added by default. Uploading images is one of those default things you’ll get on the numerous blogging platforms (in any language) available, but it’s not a built-in functionality of
rails new itself. Thus, to be able to upload images to the server that hosts this blog, the functionality must be added, and it must be added by me. It’s not a difficult process per se, but it’s a process and concept that’s intimidated me for a while, but it’s about time i face that intimidation and move forward. The first step in something like this is just the idea of testing it out using a dummy application.
In an ebook that i purchased called Practicing Rails, one of the ideas that had the greatest impact on me was the idea of the tinyapp. A simple principle really, but until I read this book, I hadn’t really made the intuitive leap required to realize this on my own. In my own words:
>Tinyapps are very useful you want to learn something new, or experiment with an idea. Create a new rails app, with an appropriate name, and use it to focus on the idea/gem you want to learn about. So in this instance, though I’m loathe to at any other time, scaffolding can be used to lay down the basic foundation of your MVC upon which you can run your experiments, or test out your new gem/plug-in. (The principle is not rails specific of course, but it’s the environment that brought the tinyapp idea to my attention.)
Like I said, a simple, rather obvious, idea but one that hadn’t occurred to me. In general, I would just throw what I’m trying to learn next into my main app, preferably on a git branch, but not always (as sometimes I get impatient) and just keep changing things until this new thing works properly. The problem with that is you can totally and completely screw up your main app, and you don’t really want to do that, do you? So instead, use tinyapps. Heck make a folder somewhere called tinyapps. That way they’re all stored in the same place for reference in the future. (Thus the reason for naming them in a way that identifies what you were trying to work out).
Applying the tinyapps idea, to uploading, I’m going to start with experimenting with the two most popular image uploaders in Rails; Carrierwave and Paperclip. Though I’ve never directly used either of these gems, I have done some reading in various places, and Paperclip always seemed to be the better option to me, but it makes sense to try out at least one more (if I find more while learning these two that appeal to me I might give them a shot) just to see if my intuition about Paperclip is correct.
Testing out Paperclip
So, as stated above, the first step is to create the tinyapp I’ll be using for my Paperclip testing. I creatively named the app paperclip, and then headed straight to the github repository, because, well, that’s the best place to go when you want to start working with a popular well-maintained gem. Paperclip was created (and is maintained) by Thoughtbot, which, from what I can tell, has a solid reputation for things like this, and has more than a couple well reviewed (all those stars) ruby gems.
As we learned in an earlier article, thorough reading of the documentation is vital. It gives an introduction and helps us avoid mistakes in the future. Paperclip has very thorough documentation, some of which I understand and find useful, some of which I don’t understand but it would still be useful to understand it in the future, and some which downright befuddles me at the moment. And while it gave me some guidance, I still feel like a bit more would be helpful before getting started.
I recently discovered a new video tutorial site, which, so far, is free, and is helpful to me. RubyThursday is a good introduction to a variety of things though I’m still going through the videos to date. The site helped me get started with setting up a Digital Ocean droplet as I try to learn the command line so I can deploy and know what I’m doing better in the future. A quick search indicates that the site does have a Paperclip tutorial which I watched as my next step.
10 Minutes Later
Well, that wasn’t as helpful as I had hoped. It’s a pretty sparse introduction to setting it up, and it does involve testing, which I’m not using at the moment, but it was a good start. On to our second video, via the wonder Railscasts, and while it’s a video from 2008, I have no doubt it should provide me with some more guidance.
Another 10 Minutes Later
A bit more information learned and transformed into current working versions of Paperclip. Still feeling like I need a bit more. To the miraculous interwebz I went and found this article published much more recently. Though the articles formatting is in desperate need of work, it did provide enough information to me to be confident enough to move forward with trying this out.
So, I read the github documentation, I watched two intro videos and read one more article. Through each, I believe I have gleaned enough information to start the basics of seeing how to implement paperclip in a basic way, and by basic, I mean, following the general guidelines to get Paperclip to work how it’s supposed to work.
This will include:
- Setting up Paperclip to upload files
- Size processing of a couple sizes
- Displaying the photo’s and their related important information (the URL being the most important for now)
This will not include:
- Doing any testing to make sure it’s done properly
- Dealing with remote storage (in the long run S3 is probably the way to go but that’s another lesson (and article) for another time)
- Integrating with a name space. Obviously on this site, I’ll need to put the paperclip functionality behind the admin wall (for now).
So what I’m going to do is follow the ‘migration’ pattern for this because I like that way it sets up in my mind for understanding. The first thing I do is create a simple MVC foundation via scaffolding for a Photo model that has one text attribute, name. I like the idea of assigning my own name to the photo even though Paperclip adds a name attribute for the uploaded file itself.
At first, I tried to write a general migration,
rails generate migration AddPictureToPhotos picture:attachment, but that code didn’t match what the demo guide had indicated so I went back and follow the guide more closely and used
rails generate paperclip photo picture. The add_attachment in the generated migration file is obviously created by and specific to Paperclip itself. This functionality, interestingly, still creates both up and down methods as opposed to the migration standard which creates a change method. (I suppose some ambitious person could re-write the code so that it creates a similar ‘default’ migration, with it being open source at all, but I’m not that ambitious to mess with gems with their on migration functionality just yet).
So now I had a properly formatted migration file to add the Paperclip functionality, and of course, migrations are no good if you don’t migrate them, which of course I promptly did and now my database table was set up for paperclip. A quick jump into my rails console indicated that the four attributes indicated in the documentation were actually created (I used
Photo.new to check it out).
I then followed the steps within the quickstart to set up the basics (no validation optoins just yet) within the model file and form to see if I could successfully set up basic file upload. I modified the
show.html.erb file to display the image using
image_tag and the url method added by using Paperclip.
After shaking of some rust (I haven’t written any code in the past 5 weeks or so due to various ‘real life’ issues getting in the way) in terms of properly formatting my erb, and where parentheses should and shouldn’t go, I came upon the first error that seemed to be Paperclip related;
Paperclip::Errors::MissingRequiredValidatorError. As (almost) always, StackOverflow came to the rescue. So it seems that the validation in the quick start guide is required, so it was copied, pasted, and formatted to fit my attribute naming conventions.
And just like that, I was able to upload a photo and get the url location for it so that I could link to it directly is desired.
The photo uploaded was a rather large one, a screen shot that would apply to an article I wrote for a different blog regarding how to do a basic contribution to a git repository, so the obvious next step is to work on resizing it. This is also covered in the quick guides with the
style statement, so I followed the guide to create a 50x50 thumbnail (scaled properly) of any uploaded photo.
That went more smoothly, and worked on the first try.
So I had successfully completed what I set out to do with Paperclip as stated above. Now, onward, to Carrierwave.
As before with Paperclip, the github documentation itself is where we start. It becomes clearly quickly that the two gems have a very different functionality but are also both currently maintained with a strong community that creates useful help like the documentation section.
The Carrierwave documentation, like paperclip, is quite thorough. I’m beginning to get the feeling, assuming I can follow the set up process for it properly, that Carrierwave might be the better option, though I should explore a few more outlets for investigation.
While RubyThursday does not have any information on working with Carrier, GoRails does have an interesting tutorial. Not only does it teach you how to get started with Carrierwave, the first half of the video goes through the process of setting up manual file upload (and no image manipulation) with Rails as a sort of demonstration why you should use a gem like Carrierwave (or Paperclip). The convolutions of setting up even one file upload with out any manipulation just make it clear that if you want to have a lot of photos uploaded, you should definitely use a gem. It’s helpful though to see the basics sometimes to get an idea what processes the gem is doing for you. The rest of the video goes through the real basics of adding Carrierwave to your application. There’s no processing involved, just the basic steps of creating an uploader and mounting it. While not more informative than the documentation, it was still helpful as I understood the actions taken in the video.
From GoRails, I went to the ever helpful (if no longer maintained sadly) Railscasts which has quite a few videos that deal with Carrierwave, directly or indirectly, but for now I want to focus directly on setting up Carrierwave. Though much older than the GoRails video, this video was also helpful in reinforcing the basic set up, while also giving a little insight on resizing.
At this point, I’m further moved towards Carrierwave over Paperclip due to the encapsulation used in Carrierwave via the uploader class. From the videos I watched so far, this standard OOP set up in Carrierwave makes things cleaner and easier to work with if you want to make changes or add different processing methods to different model uploads. Additionally, from the little I’ve seen, Carrierwave does seem easier to work with with cloud uploads if such a thing ever becomes relevant, but first, I had to work on the basics of setting it up.
As above with Paperclip, I’m narrowly focused on just getting started with Carrierwave, and not the broader concepts of testing or integration that I’ll deal with later on when I pick my uploader, and, as above, the first step is the tinyapp, that I will call carrierwave. The basic scaffold will be set up and then I’ll run through the steps provided by the documentation and video to set up the basic Carrierwave functionality.
Though different in how they work, the fundamental steps of installing Carrierwave to do its basic are the same as Paperclip, so i was able to get it up and running slightly faster than with Paperclip. However, there’s a few
resize methods that are referenced that I felt it would be helpful to understand. After some web search fumbling I found Rmagick documentation that was helpful in understanding the differences in the
resize methods (while also providing a lot more information about what Rmagick can do that might be useful later).
After running through working with both Carrierwave and Paperclip, my original thought that I would go with Paperclip has been borne out to be wrong and I will move forward with Carrierwave. I don’t see that either one is a ‘wrong’ decision, but the encapsulation that Carrierwave comes with does provide, in my mind, a method to deal with images that also allows for cleaner separated code. In Carrierwave, image processing is dealt with within a separate class, whereas in Paperclip you deal with it within the related model. It seems to me that over time or with heavy processing (if you have a reason), using Paperclip could make your model very messy, whereas the separation within Carrierwave means that your models will still stay clean. There are other names I have come upon while doing this (most notably dragonfly and refile) that probably bear some review, but that is for a later time, for now, I will go with Carrierwave. Of course, it’s not as simple as just setting it up as was done in this article. To properly install it into my app I must not only test my installations but set it up properly so that only allowed users can have access to uploading/viewing/removing images. At this point, the allowed user is only me, but it still must sit be set up ‘behind’ the admin namespace well before I could put it live on the site, which, of course, would seem like the next step.
Until we meet again.