编写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。
我的建议是删除过度工程并再试一次;-)
- 为什么不/ do和{}总是等价?
- 不兼容的库版本:nokogiri.bundle需要8.0.0或更高版本,但libiconv.2.dylib提供版本7.0.0
- 使用元编程来包围类中的方法
- Ruby Unit :: Test通过忽略空格来比较html输出
- Ruby On Rails Active Admin has_many更改文本以使用不同的列
- 如何使用ThinkingSphinx对多个模型进行地理搜索?
- presenter rails中的未定义方法`content_for’
- 对于不同类型的Ruby应用程序,最常用的unit testing框架是什么?
- 编码:: UndefinedConversionError:“\ xE4”从ASCII-8BIT到UTF-8