Skip to content

Instantly share code, notes, and snippets.

@olistik
Last active December 28, 2015 23:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save olistik/7583160 to your computer and use it in GitHub Desktop.
Save olistik/7583160 to your computer and use it in GitHub Desktop.
Trying to handle Singleton in a more flexible way
=begin
PRO:
* Configuration is easily testable (you can reset the singleton before each test)
* Configuration keeps Singleton behavior outside of its responabilities
=end
class Configuration
def initialize(path: nil)
puts "#initialize"
@path = path
# do some stuff, for example load the yaml located at @path
end
# define here the required helper methods
end
# ==> nil
module ConfigurableSingleton
def self.included(base)
base.class_eval do
def self.setup(**options)
@instance = reference_class.new(options) unless @instance
end
def self.instance
@instance || raise('init with .setup first')
end
def self.reset
@instance = nil
end
private_class_method :new
def self.reference_class
@reference_class || raise('provide a reference class with .use_class')
end
def self.use_class(klass)
@reference_class = klass
end
end
end
end
# ==> nil
class ConfigurationProvider
include ConfigurableSingleton
use_class Configuration
end
# ==> Configuration
ConfigurationProvider.setup(path: 'foo')
# =#initialize
# ==> #<Configuration:0x007f91da102840 @path="foo">
ConfigurationProvider.instance
# ==> #<Configuration:0x007f91da102840 @path="foo">
ConfigurationProvider.reset
# ==> nil
ConfigurationProvider.setup(path: 'moo')
# =#initialize
# ==> #<Configuration:0x007f91da8b6be0 @path="moo">
ConfigurationProvider.instance
# ==> #<Configuration:0x007f91da8b6be0 @path="moo">
ConfigurationProvider.new
# =NoMethodError: private method `new' called for ConfigurationProvider:Class
# = from (irb):54
# = from /usr/bin/irb:12:in `<main>'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment