public
Last active

Trying to handle Singleton in a more flexible way

  • Download Gist
gistfile1.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
=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>'

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.