我有一个包含API的Ruby gem。我有两个类:Client
和Season
,带有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"我希望puts
类Season
方法中的self.all
打印出来" ak"和" http://ep.com",而是我在Configuration
部分设置了默认设置。
我做错了什么?
答案 0 :(得分:1)
api_key
和Client
上的ApiWrapper
个访问者是独立的。您使用所需的密钥初始化Client
,然后Season
直接引用ApiWrapper
。您已在三个位置声明api_key
等访问者:ApiWrapper::Configuration
,ApiWrapper
(通过扩展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_key
和endpoint
,则在设置时不需要Client
至今。只需直接设置ApiWrapper.api_key
并继续在Season
中使用它。