包装API的Gem不能使API密钥设置器在所有类中都能工作

时间:2015-10-31 14:03:31

标签: ruby-on-rails ruby api

我有一个包含API的Ruby gem。我有两个类:ClientSeason,带有Configuration模块。但我无法通过Client类中的Season访问对API Key,Endpoint的更改。

我的ApiWrapper模块如下所示:

require "api_wrapper/version"
require 'api_wrapper/configuration'
require_relative "api_wrapper/client"
require_relative "api_wrapper/season"

module ApiWrapper
    extend Configuration
end

我的Configuration模块如下所示:

module ApiWrapper
   module Configuration
       VALID_CONNECTION_KEYS = [:endpoint, :user_agent, :method].freeze
       VALID_OPTIONS_KEYS    = [:api_key, :format].freeze
       VALID_CONFIG_KEYS     = VALID_CONNECTION_KEYS + VALID_OPTIONS_KEYS

       DEFAULT_ENDPOINT    = 'http://defaulturl.com'
       DEFAULT_METHOD      = :get

       DEFAULT_API_KEY      = nil
       DEFAULT_FORMAT       = :json


       attr_accessor *VALID_CONFIG_KEYS

      def self.extended(base)
        base.reset
      end

      def reset
          self.endpoint   = DEFAULT_ENDPOINT
          self.method     = DEFAULT_METHOD
          self.user_agent = DEFAULT_USER_AGENT

          self.api_key    = DEFAULT_API_KEY
          self.format     = DEFAULT_FORMAT
      end

      def configure
          yield self
      end

      def options
        Hash[ * VALID_CONFIG_KEYS.map { |key| [key, send(key)] }.flatten ]
      end

  end # Configuration
end

我的Client课程如下:

module ApiWrapper
    class Client
        attr_accessor *Configuration::VALID_CONFIG_KEYS

        def initialize(options={})
            merged_options = ApiWrapper.options.merge(options)

            Configuration::VALID_CONFIG_KEYS.each do |key|
               send("#{key}=", merged_options[key])
            end
         end

    end # Client
 end

我的Season课程如下:

require 'faraday'
require 'json'

API_URL = "/seasons"

module ApiWrapper
    class Season
        attr_accessor *Configuration::VALID_CONFIG_KEYS
        attr_reader :id

        def initialize(attributes)
            @id = attributes["_links"]["self"]["href"]
            ...
        end

        def self.all
            puts ApiWrapper.api_key
            puts ApiWrapper.endpoint
            conn = Faraday.new
            response = Faraday.get("#{ApiWrapper.endpoint}#{API_URL}/") do |request|
                request.headers['X-Auth-Token'] = "ApiWrapper.api_key"
            end
            seasons = JSON.parse(response.body)
            seasons.map { |attributes| new(attributes) }
        end

    end
end

这是我正在运行的测试:

def test_it_gives_back_a_seasons
    VCR.use_cassette("season") do
        @config = {
          :api_key    => 'ak',
          :endpoint   => 'http://ep.com',
        }

        client = ApiWrapper::Client.new(@config)
        result = ApiWrapper::Season.all

        # Make sure we got all season data      
            assert_equal 12, result.length

        #Make sure that the JSON was parsed
            assert result.kind_of?(Array)
            assert result.first.kind_of?(ApiWrapper::Season)
    end
  end

因为我通过客户端将api_key设置为" ak"和#34; http://ep.com"我希望putsSeason方法中的self.all打印出来" ak"和" http://ep.com",而是我在Configuration部分设置了默认设置。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

api_keyClient上的ApiWrapper个访问者是独立的。您使用所需的密钥初始化Client,然后Season直接引用ApiWrapper。您已在三个位置声明api_key等访问者:ApiWrapper::ConfigurationApiWrapper(通过扩展Configuration)和Client。您应该弄清楚您的用例是什么,并将其减少到一个地方以避免混淆。

如果您在提出不同请求时要让许多客户端使用不同的API密钥,则应将客户端注入Season并使用它而不是ApiWrapper。这可能是这样的:

def self.all(client)
  puts client.api_key
  puts client.endpoint
  conn = Faraday.new
  response = Faraday.get("#{client.endpoint}#{API_URL}/") do |request|
      request.headers['X-Auth-Token'] = client.api_key
  end
  seasons = JSON.parse(response.body)
  seasons.map { |attributes| new(attributes) }
end

请注意,我还将"ApiWrapper.api_key"字符串替换为client.api_key - 您不希望它仍然是字符串。

必须将client传递给您所做的每个请求都会变老,所以您可能需要提取类似SeasonQuery类的内容来保留它。

如果您在执行期间只有一个api_keyendpoint,则在设置时不需要Client至今。只需直接设置ApiWrapper.api_key并继续在Season中使用它。