Deep Dive: Implementing Custom File Upload Button Styles and Refactoring Placeholder Images
In this final guide of the section we'll walk through how to add custom styles to Bootstrap file upload buttons. Additionally, we'll walk through a debugging session where we refactor the image placeholder tool that was originally a model concern.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Now that image uploader is working properly, let's attack this ugliness right here. For some reason, HTML just does not like having good looking file uploading buttons.

Switch to sublime, there are a few ways of customizing the button. A straightforward way of doing it is to repurpose the label.

I'm going to actually use a label tag. I'm going to slide the file field inside of the label. I can say upload main image file and then on the same line, I'm going to put this file field. Inside of this, I am going to pass in a style and then in quotes, I'm going to say display:none. This is simply going to hide the button. Since the button is wrapped inside the label this is all going to live. The file field is actually going to be invisible but it's going to be nested inside the label. If you click the label it is going to activate the file field which is exactly what we want.

I'm going to copy this and paste it right down here, instead of saying main image we will say thumb image.

Come back to Chrome, refresh, that looks much better.

Let's make sure they're functional, I'm going to upload main image and thumb image. I'm going to save it and you can see the image was uploaded.

One other cleanup item, open up our portfolio.rb file. Remember we have this placeholder, this is a concern that we implemented. The reason this is not working is that we have here is our main image, which is now a very special kind of attribute. Whenever we have this mount uploader for an item, our portfolio uploader is overriding everything. This is no longer treated as a plain old text field. Now this is a very special carrier wave field and simply trying to pipe in our image generator of our placeholder is simply not going to work anymore.

Let's open the portfolio_helper.rb and update it to this

We can delete the placeholder.rb file completely.

We're going to create an image helper, in the portfolio.rb file, get rid of the validates presence of main image and thumb image. Inside of portfolio_helper.rb we're going to create a new method.

def portfolio_img img, type
  if img
  elsif type == 'thumb'
    image_generator(height: '350', width: '200)
    image_generator(height: '600', width: '400')

Inside it's going to do is say if an image is provided (someone has uploaded an image) then simply return the image don't do anything to it. Next, elseif, type is equal to thumb then I want you to use our image generator method here and we're going to pass in some specific values. Let me copy this and then we'll give one final else, this is simply going to return our main image. All we're really doing here is we're providing a set of defaults, instead of handling them in the model we're going to handle them right here.

Next we have to call this from the view.

<%= image_tag portfolio_img(portfolio_item.thumb_image, 'thumb') %>

We're going to call image tag on portfolio image and pass in portfolio item. If that's not totally clear don't worry, think back to what we created here. This portfolio image is a method, It expects an image, we pass that in. The image might be nil, in that case, then this whole placeholder process goes into play.

Now let's go to the terminal and type rails db:setup this is going to wipe out all of our test data and give us new data to work with. I see that we have an error in the skill placeholder.

Let's open skill.rb and update the file to:

class Skill < ApplicationRecord
  validates_presence_of :title, :percent_utilized

Go to the terminal and type rails db:setup and that should clear the errors.

If we go back to the app and refresh the portfolio page, notice that we aren't getting those errors that we had before but now are placeholders not working. What gives? I'm going to come into the portfolio_helper.rb and let's implement byebug. Hit refresh, now let's take a look at this. Here is the problem, right here. Image is no nil, it is actually going to be treated like a portfolio uploader object. We need is to check to see if img. thumb_image || img.main_image are nil. Exit out of byebug.

Remove byebug and update the file to:

def portfolio_img img, type
  if img.module.main_image? || img.model.thumb_image?
  elsif type == 'thumb'
    image_generator(height: '350', width: '200)
  elseif type == 'main'
    image_generator(height: '600', width: '400')

Hit refresh, everything is now working.

Our show page needs to be updated to this:

Everything is working.

I wanted you to see when I run into bugs, you're going to run into bugs when you're building out apps. I was constantly trying to figure out what is the data telling me, the data is going to give all the clues. Imagine if I would have tried to figure that bug out without using byebug, that would have taken astronomically longer.

  • git status
  • git add .
  • git commit -m "Updated file upload forms and refactored placeholder functionality into view"
  • git push origin image-management

Let's create a pull request from GitHub

  • create & pull request
  • create pull request
  • merge pull request
  • confirm merge

In the terminal let's pull all the code down

  • git checkout master
  • git pull

Great job, I know that was a very long deep dive that stretched a number of videos. In the next section, we're going to take a deeper dive into our forms and we're going to learn all about how Rails utilizes forms.