我正在编写一个我想要使用的gem而没有Rails环境。
我有一个Configuration
类来允许配置gem:
module NameChecker
class Configuration
attr_accessor :api_key, :log_level
def initialize
self.api_key = nil
self.log_level = 'info'
end
end
class << self
attr_accessor :configuration
end
def self.configure
self.configuration ||= Configuration.new
yield(configuration) if block_given?
end
end
现在可以这样使用:
NameChecker.configure do |config|
config.api_key = 'dfskljkf'
end
但是,我似乎无法通过我的gem中的其他类访问我的配置变量。例如,当我在spec_helper.rb
中配置gem时,如下所示:
# spec/spec_helper.rb
require "name_checker"
NameChecker.configure do |config|
config.api_key = 'dfskljkf'
end
并从我的代码中引用配置:
# lib/name_checker/net_checker.rb
module NameChecker
class NetChecker
p NameChecker.configuration.api_key
end
end
我收到一个未定义的方法错误:
`<class:NetChecker>': undefined method `api_key' for nil:NilClass (NoMethodError)
我的代码出了什么问题?
答案 0 :(得分:18)
尝试重构:
def self.configuration
@configuration ||= Configuration.new
end
def self.configure
yield(configuration) if block_given?
end
答案 1 :(得分:-2)
主要问题是你应用了太多的间接。你为什么不这样做
module NameChecker
class << self
attr_accessor :api_key, :log_level
end
end
并完成它?您也可以在之后覆盖两个生成的阅读器,以确保它们存在您所需的环境......
module NameChecker
class << self
attr_accessor :api_key, :log_level
def api_key
raise "NameChecker really needs is't api_key set to work" unless @api_key
@api_key
end
DEFAULT_LOG_LEVEL = 'info'
def log_level
@log_level || DEFAULT_LOG_LEVEL
end
end
end
现在,实际(技术)问题是您正在定义一个名为NetChecker
的类,并且在定义它时,您尝试在假定的{{1}上打印api_key
调用的返回值对象(所以你在这里违反了得墨忒耳的法则)。这失败了,因为在任何人真正有时间定义任何配置之前,您正在定义Configuration
。因此,在NetChecker
上调用api_key
方法之前,您实际上是在请求configure
,因此NameChecker
ivar中有nil
。
我的建议是删除过度工程并再试一次; - )