编写gem时设置配置设置

我正在写一个我想要使用的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_helper.rb所示:

 # 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 

我得到一个未定义的方法错误:

 `': undefined method `api_key' for nil:NilClass (NoMethodError) 

我的代码出了什么问题?

尝试重构:

 def self.configuration @configuration ||= Configuration.new end def self.configure yield(configuration) if block_given? end 

主要问题是你应用了太多的间接。 你为什么不这样做呢

 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的类,并且在定义它时,您尝试在假定的Configuration对象上打印api_key调用的返回值(因此您违反了Demeter法则)。 这失败了,因为在任何人真正有时间定义任何配置之前,您正在定义NetChecker 。 因此,在api_key上调用configure方法之前,您实际上是在请求api_key ,因此它的configuration ivar。

我的建议是删除过度工程并再试一次;-)