Build Your Own YouTube Thumbnail Downloader! RoR+SerpApi - Part 1
Tags: tutorial, rails, beginners, api
Published: 2024-07-06 12:15:21

## Part 1 - Basic Working Example (Done)
## Part 2 - Refactor and Deployment

In this short tutorial we'll build a simple YouTube thumbnail downloader in Ruby on Rails with SerpApi for finding video thumbnails.

## Prerequisites:- 

Ruby version 3.2.2
Ruby on Rails version 7.1.3.4
SerpApi access. You can get the api key by singing up [here](https://serpapi.com/).

The versions don't matter. You should have both ruby and rails installed in your system.

Let's begin by scaffolding our rails app.
`$ rails new YT-Thumbnail-Downloader`

Go to the project directory `$ cd YT-Thumbnail-Downloader`.

Type `$ rails s` in the terminal and open localhost:3000 in the browser. You should see the default home page for the rails app.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p1olsjh9o6bii3lf46bh.png)

If you can see the rails default page then everything is working fine.

## The Structure of the App.

We'll build a basic working app in part 1 and refactor our code in part 2 of the article.

The app will have one controller and a single view template. There's no model for now. We'll simply make a call to the YouTube Video API from SerpApi and serve the result on the home page.

## Controller

We can use the rails generate command to create controllers. But in this article we'll do it manually.

In your rails app directory inside the app/controller create a home_controller.rb file.

`$ touch app/controller/home_controller.rb`

Now create the index action for home controller.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpnymf7txcdnc65mzfuf.png)

We'll use only one controller action for the app logic to keep things simple. 

## SerpApi

Next, we need to make a call to the api. For that grab your api key from SerpApi. You can find your key in your account dashboard.

To work with api, we can use several ruby gems. But for this article  we'll stick with the standard HTTP library. 

From your SerpApi account select youtube video api from the left panel and scroll down the api examples. 

Copy the [example link](https://serpapi.com/youtube-video-api) from from there. It should look like this. https://serpapi.com/search.json?engine=youtube_video&v=vFcS080VYQ0

Clicking on the link will take you the results page. The json response here gives the data of youtube video beign scraped by the SerpApi.

If you look closely, you can find the thumbnail of the video with a link to the high resolution image. Parsing this thumnail is all we need to do. 

Let's look at the link from SerpApi. The link returns a json response, it has an engine that defines its purpose (engine=youtube_video). In our case its youtube video api. Don't confuse it with the parent YouTube api. The last query in the link is the id of the video(v=vFcS080VYQ0). Every YouTube video has an ID. We only need to switch this id in the api call to fetch the thumbnail. Interesting video on the topic [here](https://www.youtube.com/watch?v=gocwRvLhDf8).

Let's add all this in our controller.

## Making the API call

To make the api call we'll use the standard ruby http library. First  save the link in variable url.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ph4s0x1jhysusg808mp9.png)

To make authenticated call to the SerpApi you need to add the api key at the end of this url. 

`https://serpapi.com/search.json?engine=youtube_video&v=vFcS080VYQ0&api_key={your api key goes here}`

Ideally, you should use something like dotenv for rails to save your api keys. We'll do it in the second part of the article. 

Let's start with making the api call. For that, you need to use URI module. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9cnslxv3b5zejhcgv8gm.png)

Like so. Next we need to save the response.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtqtc14h50db1l08u32s.png)

To check wether the api is connected, insert raise right below the response. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdxhq7kt7nsma9d0vapy.png)

Restart the server and you should see the error page. Below in the console make the call to api by typing `$ res`. 

If you see HTTP 200 OK that means your api is working!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vsvprn9rwrdd0dmvasxt.png)

If you type `$ res.body` inside console, you'll see hash response. We need to save this data inside a variable and parse the thumbnail.

## Parsing and Displaying The Thumbnail

We have the data of the YouTube video and all that we need to do now is to extract the thumbnail.

To do this we'll store the response body in a data variable and parse it for thumbnail. Check out the code in below screen shot.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6rfzm26n0x03nml0bjx9.png) 

Insert raise below the `$ @data` variable and go to the browser and refresh the page. 

In the console type this line `$ @data`. To parse this data, simply parse it as you would parse any other array of data from a json response.

The api gives us all the data for the present video and its channel. To see the number of subscribers you can do `$ @data["channel"]["subscribers"]`. 

But want the thumbnail. For that, use `$ @data["thumbnail"]`. This should return an image link.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19ai920jxnqcn7wiqv7u.png)

Like so.

Copy and paste this link to see the thumbnail.

Let's store this image link to a variable and render the thumbnail.

## The Views

Create the 'home' folder for the views template. `$ mkdir app/views/home`.

Next create a view index template for the index action of the home controller `$ touch app/views/home/index.html.erb`. Make sure its inside the home folder.

The templates are based on the controller action. Here the controller is 'home' with only one action that is 'index'. The erb is the template extension for rails.

Remove `$ raise` from your controller.

Open up the index view template and create h1 tag with the contents `$ <h1>YT Thumbnial Downloader!</h1>`.

Before refreshing your home page, make sure you update your route.rb file's root route to `$ root 'home#index'.

Go to your app home page localhost:3000 and refresh the page.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9o5q0i8k0w05vi5pxssp.png)

You should see the same page as above.

All that we need to do is to render the thumbnail image on the home page of our app.

We'll need to create another variable `$ @image` in our home controller `$ @image = @data["thumbnail"]`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmb7nhb94i3rh15p83an.png)

`@` in front of a variable in ruby makes it a global instance that you can access globally in your app.

Now render the image in your views `$ <img src="<%= @image %>" alt="youtube thumbnail image">`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14m7oheq49a8aonsptg1.png)

Refresh the home page and you should see the video thumbnail.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/agi2xdgguh08ti5jhlug.png)

Right now the video id of the youtube video is hard coded. We need to accept the client input and dynamically change the thumbnail.

## The Client Interaction

We need a form in our views to accept user input in our app's frontend.

We'll use form_with helper from rails. Checkout the screenshot below with the completed form for our app.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mrlbywpz73sl9oevt184.png) 

We'll use form_with to send the input from the client/frontend to the home controller.

You can use model or url for form_with. Since, we aren't using any model in our app we'll stick with url.

The line below h1 tag in the above screen shot is the image tag that will display the thumbnail image.

The first line of form_with will direct the form input to the root route. `$ url: '/'`. The method is get, remember that we are making a get request to SerpApi. Next, the data turbo value set to true is optional. In rails the turbo is true by defualt. If you face any problem with the form you can try toggle the value to false. 

The form.label will show up on the forntend to let the user know where to input the YouTube video link. Whereas, form.text_field allows for data transfer between the controller and the view.

And form.submit will submit the form. 

Now all that we need to do is to update our home controller so that we can complete the app.

Take a look at the screenshot below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/30xxssgtq051ubwp94cn.png)

The youtube video link is passed as params. The :v could be named anything. It stores the actual link, which is then again stored inside variable 'id'. Using URI.query method gives us the youtube video id. String after the "?" in a url is a query.

Replace the video id in the SerpApi link with the vriable 'id' as its shown in the screenshot. 

And that's it! Now you can copy any YouTube video link and get its thumbnail.

Test this YouTube video link: [Harnessing the True Power of Regular Expressions in Ruby](https://www.youtube.com/watch?v=JfwS4ibJFDw)

You should get this thumbnail:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3cj87xor686r382kqngf.png)

Will cover refactoring and deployment in part 2.

This app works only when the video link is copied from the YouTube. If you get a shared link then this setup won't work. Read more on YouTube video id [here]
(https://gist.github.com/jakebellacera/d81bbf12b99448188f183141e6696817).


Cover Photo by <a href="https://unsplash.com/@vmxhu?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Szabo Viktor</a> on <a href="https://unsplash.com/photos/youtube-website-screengrab-4QmSdCP4bhM?utm_content=creditCopyText&utm_medium=referral&utm_source=unsplash">Unsplash</a>