写一个宝石时设置的配置设置(Setting up configuration settings wh

2019-07-29 09:19发布

我写,我想使用和不使用Rails的环境中工作的瑰宝。

我有一个Configuration类,允许创业板的配置:

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

不过,我似乎并没有能够从我的宝石withing其他类访问我的配置变量。 例如,当我配置的宝石在我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

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

`<class:NetChecker>': undefined method `api_key' for nil:NilClass (NoMethodError)

什么是错我的代码?

Answer 1:

尝试重构到:

def self.configuration
  @configuration ||=  Configuration.new
end

def self.configure
  yield(configuration) if block_given?
end


Answer 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 ,虽然它定义您要打印的返回值api_key假设呼叫Configuration对象(原来你也在这里违反迪米特法则)。 这种失败,因为你定义NetChecker真的有人有时间来定义任何配置之前。 所以,你实际上请求api_key的前configure方法被调用的NameChecker ,因此它具有nil在它的configuration伊娃。

我的建议是去除过度设计,然后再试一次;-)



文章来源: Setting up configuration settings when writing a gem
标签: ruby rubygems