如何重构 IEX 交换数据调用以从 ruby 程序中的 api 抓取数据

how to refactor IEX exchange data calls for grabbing data from api in ruby program

我正在使用 iex 交易所 api 来获取有关股票的信息。它运行良好,但我的代码非常难看,想知道如何重构代码。

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

这是获取信息所需要的。问题是我必须将上面的代码放在每个使用 api 的方法中。例如,

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

有没有什么方法可以考虑调用不同的文件并以这种方式调用方法?代码是非常重复的。 "stock" 变量是我实际需要使用的变量,我应该将其设为全局变量吗?我听说这是一个禁忌,但这种情况是例外吗?另外,我有

publishable_token: token,

那个令牌变量实际上是我实际的硬编码令牌,而不是您看到的 "token" 变量,我只是出于安全问题更改了它。我应该怎么做而不是对其进行硬编码?文档说要把它变成一个环境变量,但我不知道那是什么意思。提前致谢!

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.

environment variable 是一个变量,其值是在应用程序外部设置的,通常是通过操作系统内置的功能或 shell。您需要查看设置文档以了解如何设置环境变量。

您可以通过 ENV 哈希在 Ruby 中获取环境变量。

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

Rails 5.2 及更高版本有 secure credentials 可以代替使用。它将您的凭据存储在一个加密的 YAML 文件中,该文件可以签入源代码管理。

How do I refactor this?

重构它的一种方法是使用委托而不是一堆主要是静态的方法:

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)