I'm trying to write the most secure singleton in Ruby that I can. I'm new to the language, which is so elastic that I don't have a strong feeling that my singleton class will be successful at creating only one instance. As a bonus, I'd like the object to only become instantiated if really used.
Singleton class is object specific anonymous class that is automatically created and inserted into the inheritance hierarchy. singleton_methods can be called on an object to get the list of of names for all of the singleton methods on an object.
The singleton pattern is one of the simplest design patterns. Sometimes we need to have only one instance of our class for example a single DB connection shared by multiple objects as creating a separate DB connection for every object may be costly.
# require singleton lib
require 'singleton'
class AppConfig
# mixin the singleton module
include Singleton
# do the actual app configuration
def load_config(file)
# do your work here
puts "Application configuration file was loaded from file: #{file}"
end
end
conf1 = AppConfig.instance
conf1.load_config "/home/khelll/conf.yml"
#=>Application configuration file was loaded from file: /home/khelll/conf.yml
conf2 = AppConfig.instance
puts conf1 == conf2
#=>true
# notice the following 2 lines won’t work
AppConfig.new rescue(puts $!)
#=> new method is private
# dup won’t work
conf1.dup rescue(puts $!)
#=>private method `new’ called for AppConfig:Class
#=>can’t dup instance of singleton AppConfig
So what does ruby do when you include the singleton module inside your class?
new
method private and so you can’t use it.So to use ruby singleton module you need two things:
singleton
then include it inside the desired class.instance
method to get the instance you need.If you want to create a singleton, why bother creating a class? Just create an object, and add the methods and instance variables to it you want.
>> MySingleton = Object.new
=> #<Object:0x100390318>
>> MySingleton.instance_eval do
?> @count = 0
>> def next
>> @count += 1
>> end
>> end
=> nil
>> MySingleton.next
=> 1
>> MySingleton.next
=> 2
>> MySingleton.next
=> 3
A more standard way that people implement this pattern is to use a Module
as the singleton object (rather than the more generic Object
):
>> module OtherSingleton
>> @index = -1
>> @colors = %w{ red green blue }
>> def self.change
>> @colors[(@index += 1) % @colors.size]
>> end
>> end
=> nil
>> OtherSingleton.change
=> "red"
>> OtherSingleton.change
=> "green"
>> OtherSingleton.change
=> "blue"
>> OtherSingleton.change
=> "red"
If you wanted your singleton object to inherit from some class, just make it an instance of that class. To inherit from a mixin, just use #extend
. If you want a singleton object, ruby makes it really easy, and unlike other languages, it doesn't have to be defined in a class.
Ad-hoc singletons (my first example) are all over the place, and cover the majority of cases I've encountered. The module trick normally covers the rest (when I want something a little more formal).
Ruby code should (imho) use duck typing (via #respond_to?
) rather than explicitly checking an object's class, so I normally don't care about the uniqueness of my singleton objects' class, since it's not its class that makes it unique, but everything I added after.
require 'singleton'
class Klass
include Singleton
# ...
end
See the Ruby Standard Library Singleton class documention for an explanation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With