I was reading about Singletons in Ruby. I never really had the need to use them before, but I got curious and decided to look them up, to see if I should've used them in the past, or maybe I could use them in the future if I knew what they are used for.
The only times I can think of to use this is:
Hash
object, that acts like a normal Ruby hash with a few additional quirks.However, I am not really sure I had the need for either of the above.
Work-arounds typically break the "single instance" part of a singleton. Consider a situation where you have multiple projects relying on shared code in a NetworkManager class. Even if you want this NetworkManager to be global state, and single instance, you should be very skeptical about making it into a singleton.
The primary purpose of a Singleton class is to restrict the limit of the number of object creation to only one. This often ensures that there is access control to resources, for example, socket or database connection.
The Singleton Ruby mixin itself is thread safe. It means that you are guaranteed to get the same instance in all threads, and only that! It doesn't mean that methods which you implement for a singleton class by yourself will be thread safe.
A singleton class of an object (or a class) is a class created by Ruby only for this specific object. This class is somehow “hidden” to us, but it is there. When calling a method on this object, Ruby will look first into its singleton class, if there is one, to find that method.
Note that a class mixing in the Singleton module is functionally equivalent to a class or module with 'class' methods and either a guaranteed initialization call or inline initialization. Compare this usage of Singleton:
require 'singleton'
class Bar
include Singleton
attr_reader :jam
def initialize
@jam = 42
end
def double
@jam *= 2
end
end
b1 = Bar.instance
b1.double
b2 = Bar.instance
b2.double
p b1.jam #=> 168
with this no-magic module:
module Foo
@jam = 42
def self.double
@jam *= 2
end
def self.jam
@jam
end
end
Foo.double
Foo.double
p Foo.jam #=> 168
In both cases you have a single global object that maintains state. (Because every constant you create in the global scope, including classes and modules, is a global object.)
The only functional difference is that with the Singleton
you delay the initialization of the object until the first time you ask for it.
So, if you ever have 'class' methods on a class or module and you use those to change the state of that object (e.g. a class keeping track of all subclasses that inherit from it) you are essentially using a singleton.
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