Ответ 1
Попробуйте выполнить рефакторинг:
def self.configuration
@configuration ||= Configuration.new
end
def self.configure
yield(configuration) if block_given?
end
Я пишу драгоценный камень, с которым я бы хотел работать и без среды 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
Однако, похоже, я не могу получить доступ к своим переменным конфигурации из других классов в моем драгоценном камне. Например, когда я настраиваю жемчужину в моем 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:
`<class:NetChecker>': 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
, и при определении этого параметра вы пытаетесь напечатать возвращаемое значение вызова api_key
на предполагаемом объекте Configuration
(так что вы нарушают закон Деметры здесь). Это не удается, потому что вы определяете NetChecker
, прежде чем кто-либо действительно успел определить какую-либо конфигурацию. Таким образом, вы действительно запрашиваете api_key
до того, как метод configure
был вызван на NameChecker
, поэтому он имеет nil
в нем Configuration
ivar.
Мой совет должен был бы устранить переналадку и повторить попытку; -)