Relaying Data through a Backend API

Photo by Braden Collum on Unsplash
Insta-Space display of Mars Rover Images

Why Relay Through Your Own API?

  1. Why use my own API? Well, it turns out that using an API Key securely with a React frontend might be a bit trickier than just using your own API to keep your keys secure.
  2. Also, I want to persist the data of NASA images if, and only if, you interact with the images, such as when you click the heart to show that you like a particular image, or you add a comment to the image.
  3. Further, and this is a BIG one:

There’s a scalability issue you run into if you save ALL of the images, or data that you gather from an external API.

  • I don’t really have room to save every image I get from the NASA API, especially if I actually want to use this app frequently or for many users.
  • So, I thought,
Passing the baton in a relay race.
Photo by Magic Keegan on Unsplash

Planning Your Relay Flow

This requires planning for two things:

  1. Checking that the information isn’t already saved to your database. (Sometimes you do want to save the data, after all.) If it is saved, retrieve the persisted information.
  2. Formatting the data you are relaying so that it can easily be persisted in your database when you want to save it, and displayed on your frontend, just like any other information you’ve already saved.
class Api < ApplicationRecord
@@base_url = 'https://api.nasa.gov/mars-photos/api/v1/rovers/'
@@rover_array = ["curiosity", "spirit", "opportunity"]
@@rover_max_sol = {"curiosity" => 3241, "spirit" => 2208,
"opportunity" => 5111}
@@camera_names = {
"FHAZ" => "Front Hazard Avoidance Camera",
"RHAZ" => "Rear Hazard Avoidance Camera",
"MAST" => "Mast Camera",
"CHEMCAM" => "Chemistry and Camera Complex",
"MAHLI" => "Mars Hand Lens Imager",
"MARDI" => "Mars Descent Imager",
"NAVCAM" => "Navigation Camera",
"PANCAM" => "Panoramic Camera",
"MINITES" => "Miniature Thermal Emission Spectrometer"
}
def self.fetch_images(earth_date = nil)
# randomize rover
rover = @@rover_array[rand(2)]
max_sol = @@rover_max_sol[rover]
if earth_date
date_query = "earth_date=#{earth_date}"
else
date_query = "sol=#{rand(max_sol)}"
end
# Set data parameters to actual dates for opportunity rover in
earth_date
url = "#{@@base_url}#{rover}/photos?#{date_query}&api_key=#
{ENV["NASA_API_KEY"]}"
uri = URI(url)
resp = Net::HTTP.get(uri)
photos = JSON.parse(resp)
data = photos["photos"]
# get more data if insufficient for frontend display
data = self.format_data(data, rover).compact
if data.count < 15
data += self.fetch_images
end
data.shuffle
end
def self.format_data(data, rover)
data.map do |image_data|
if image_data["camera"] && image_data["earth_date"]
camera = @@camera_names[image_data["camera"]["name"]]
title = "#{rover.titleize} Rover—#{camera}—#{image_data["id"]}"
if saved_image = Image.find_by(title: title)
ImageSerializer.new(saved_image)
else
date = image_data["earth_date"]
{
image_url: image_data["img_src"],
title: title,
date_of_capture: date,
like_count: 0,
comment_count: 0
}
end
end
end
end
end

Data Formatting

if saved_image = Image.find_by(title: title)
ImageSerializer.new(saved_image)
else
date = image_data["earth_date"]
{
image_url: image_data["img_src"],
title: title,
date_of_capture: date,
like_count: 0,
comment_count: 0
}
end

When Found in Our Database

If the image is already saved in the database, we can find it by its unique title, which is a combination of the rover name, the camera used to take the shot, and the image id stored in the NASA database:

class ImageSerializer < ActiveModel::Serializer
attributes :id, :image_url, :title, :date_of_capture, :like_count,
:comment_count
end

When Relayed and Not Saved

If the image is not already saved in the database, we take each of the pieces of information we want to use, and which we might want to save in our database, and we return it in a hash structure that is identical to the hash-like JSON object structure we returned if the entry for this image already exists in our database:

date = image_data["earth_date"]
{
image_url: image_data["img_src"],
title: title,
date_of_capture: date,
like_count: 0,
comment_count: 0
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
David Ryan Morphew

David Ryan Morphew

I’m very excited to start a new career in Software Engineering. I love the languages, frameworks, and libraries I’ve already learned / worked with (Ruby, Rails,