This week has been project week for my bootcamp cohort. For our assignment we are to build a Ruby CLI Gem using Nokogiri to scrape HTML or an API.
I settled on the latter and decided to use CoinGecko's free cryptocurrency API. It provides data on the 100 largest crypto projects.
Below I will be briefly going over the process I went through to make this project work.
Getting Started
I started this project off using Bundle to provide a basic project structure/skeleton. It will generate the necessary files needed for creating a Ruby Gem by running bundle gem GEM_NAME
After generating my project skeleton, I filled out the necessary information in my gemspec file and began adding dependencies I knew I'd need. There are also some fields in the gemspec that must be filled out before running your bundle install command.
After the initial setup, I began to add files that I needed such as my binary, and class files. I also set up an environment file where I can include all my dependencies in one place. It is set up like this:
/gecko_api/bin/gecko_api
#!/usr/bin/env ruby
require_relative "../lib/gecko_api"
Controller.new.call
/gecko_api/lib/gecko_api.rb
require_relative "./gecko_api/version"
require_relative "./gecko_api/controller"
require_relative "./gecko_api/market"
require_relative "./gecko_api/concerns/repeatable"
require 'json'
require 'open-uri'
require 'pry'
require 'colorize'
This makes sure all of my requirements are called upon as soon as the program launches.
One of the more difficult aspects of this project happened when I unknowingly got myself stuck in an infinite loop.
I had two loops running inside of eachother that made them run forever. This happened due to the way my menu in my controller class was set up. Below is the correct working implementation.
controller.rb
def self.menu
puts "Type 'top' to view the top 100 projects by market cap."
puts "Type a number 1-100 to view detailed information about a single asset."
input = gets.chomp
integer_input = input.to_i
if integer_input > 0 and integer_input < 101
Market.coin(input)
else
case input.to_s
when "back"
Controller.clear_term
Market.top
when "top"
Market.new
Market.top
when "update"
Market.update
else
puts "Invalid command. Please try again!".colorize(:red)
Controller.menu
end
end
end
market.rb
def self.coin(number)
puts "Searching"
@@market.each do |coin|
if coin.market_cap_rank.to_s == number
id = coin.id
data = JSON.parse(open(BASE_URL + id).read)
Controller.clear_term
if data["market_data"]["price_change_percentage_24h"] > 0
print "#{data["name"].colorize(:red)} (#{data["symbol"].upcase.colorize(:red)}) " + "$".colorize(:green) + "#{data["market_data"]["current_price"]["usd"].to_s.colorize(:green)} - #{data["market_data"]["price_change_percentage_24h"].round(2).to_s.colorize(:green)}" + "%".colorize(:green)
else
print "#{data["name"].colorize(:red)} (#{data["symbol"].upcase.colorize(:red)}) " + "$".colorize(:green) + "#{data["market_data"]["current_price"]["usd"].to_s.colorize(:red)} - #{data["market_data"]["price_change_percentage_24h"].round(2).to_s.colorize(:red)}" + "%".colorize(:red)
end
# number formatting. making more human readable. outputs X.XXX Million/Billion
if data["market_data"]["market_cap"]["usd"].digits.length > 11
mktcap = "Billion"
else
mktcap = "Million"
end
# formatting the marketcap number. taking the first 6 numbers of the string.
puts " "
puts "Total Market Cap: $#{data["market_data"]["market_cap"]["usd"].to_s[0..5].insert(-4, ".")} #{mktcap}"
# project description formatting. removing HTML elements but keeps links within parentheses
description = data["description"]["en"]
puts description.gsub(/<[^"\\] href="/, '(').gsub(/["\\]>/, ') ').gsub(/<[^<\\]a>/, '')
else
print "."
end
end
puts " "
Controller.menu
end
I accidently had my Controller.menu method running inside of the @@@market iterator. This had me stumped for quite awhile, but it was eventually solved.
Conclusion
Overall, this project was a great learning experience.
The beginning seemed a bit overwhelming because I was having some issues with the bundle skeleton. But, once that was solved and I was able to finally get programming, things started coming together a lot more.
I noticed that drawing out a flow-chart or some kind of visual aid can really help in the programming process. This helped me a few times when I was stuck.
Looking forward to the Sinatra project next! Thanks for reading!
What was the hardest part about your first project?