编写gem时设置配置设置

时间:2012-05-14 13:49:23

标签: ruby rubygems

我正在编写一个我想要使用的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)

我的代码出了什么问题?

2 个答案:

答案 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

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