0

I am using the iex exchange api for grabbing info about stocks. It's working great but my code is very ugly was wondering how to refactor the code.

stock = IEX::Api::Client.new(
            publishable_token: token,
            endpoint: 'https://sandbox.iexapis.com/v1'
            )  

This is what is needed to grab the info. The problem is that I have to put the code above in every method that utilizes the api. For instance,

def self.stock_price(ticker) 
        stock = IEX::Api::Client.new(
            publishable_token: token,
            endpoint: 'https://sandbox.iexapis.com/v1'
            )  
        company = stock.company(ticker)
        quote = stock.quote(ticker.upcase) 
        puts "#{company.company_name}: #{quote.latest_price}"
    end 

    def self.week_52_high(ticker) 
        stock = IEX::Api::Client.new(
            publishable_token: token,
            endpoint: 'https://sandbox.iexapis.com/v1'
            )  
            key_stats = stock.key_stats(ticker) 
            puts "52-week high: #{key_stats.week_52_high}"
    end 

    def self.week_52_low(ticker) 
        stock = IEX::Api::Client.new(
            publishable_token: token,
            endpoint: 'https://sandbox.iexapis.com/v1'
            )  
            key_stats = stock.key_stats(ticker) 
            puts "52-week low: #{key_stats.week_52_low}"
       end

Is there any way to factor that call out to a different file and call the method that way? The code is very repetitive as is. The "stock" variable is what i need to actually work with, should I made that a global variable? I've heard that's a no-no but is this case an exception? Also, where i have

publishable_token: token,

that token variable is actually my actual, hard-coded token, not the "token" variable you see, I simply changed it for security issues. What should I do instead of hard-coding it? The documentation says to turn it into an environment variable but i dont know what that means. Thanks in advance!

goodjobbin85
  • 111
  • 8

1 Answers1

1

What should I do instead of hard-coding it? The documentation says to turn it into an environment variable but i dont know what that means.

An environment variable is a variable whose value is set outside the the application, typically through functionality built into the operating system or shell. You need to check the documentation for your setup to see how to set env vars.

You can get env vars in Ruby through the ENV hash.

ENV['FOO']
ENV.fetch('FOO') # will raise a KeyError if it is not set instead of just returning nil

Rails 5.2 and up have secure credentials that can be used instead. It stores your credentials in an encrypted YAML file that can be checked into source control.

How do I refactor this?

One way to refactor this would be to use delegation instead of bunch of largely static methods:

require 'forwardable'

class MyClient
  extend Forwardable
  TOKEN = ENV.fetch('IEX_API_TOKEN')
  ENDPOINT = ENV.fetch('IEX_API_ENDPOINT', 'https://sandbox.iexapis.com/v1')

  def_delegators :@client, :company, :quote, :key_stats

  def initialize(publishable_token: TOKEN, endpoint: ENDPOINT, client: nil)
    # This is know as constructor injection and makes it easy to mock out
    # the dependency in tests 
    @client = client || IEX::Api::Client.new(publishable_token: TOKEN, endpoint: ENDPOINT)
  end

  def stock_price(ticker)
    company_name = company(ticker).company_name
    price = quote(ticker.upcase).latest_price
    puts "#{company_name}: #{price}"
  end 

  def week_52_high(ticker) 
    puts "52-week high: #{key_stats(ticker).week_52_high}"
  end 

  def week_52_low(ticker) 
    puts "52-week low: #{key_stats(ticker).week_52_low}"
  end
end

@client = MyClient.new
@client.week_52_low(ticker)
max
  • 96,212
  • 14
  • 104
  • 165