Posts

GeckoAPI - My first Ruby program intereacting with the CoinGecko API

avatar of @treepi
25
@treepi
·
0 views
·
3 min read

https://www.youtube.com/watch?v=zj2KURM3TEA

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?