rubyinitializationsingletonparameter-passingmixins

How can I mix in Singleton to create a class that accepts initialization parameters?


I've seen how to define a class as being a singleton (how to create a singleton in Ruby):

require 'singleton'
 
class Example
  include Singleton
end

But what if I want to pass some parameters to #new when initializing that single instance? Example should always have certain properties initialized. For example, say I had a class whose sole purpose is to log to a file but it requires a name of a file to log to before it can work.

class MyLogger
  def initialize(file_name)
    @file_name = file_name
  end
end

How can I make MyLogger a singleton but make sure it gets a file_name?


Solution

  • Singleton does not provide this functionality, but instead of using singleton you could write it by yourself

    class MyLogger
      @@singleton__instance__ = nil
      @@singleton__mutex__    = Mutex.new
    
      def self.instance(file_name)
        return @@singleton__instance__ if @@singleton__instance__
    
        @@singleton__mutex__.synchronize do
          return @@singleton__instance__ if @@singleton__instance__
    
          @@singleton__instance__ = new(file_name)
        end
        @@singleton__instance__
      end
    
      private
    
      def initialize(file_name)
        @file_name = file_name
      end
      private_class_method :new
    end
    

    It should work, but I did not tested the code.

    This code forces you to use MyLogger.instance <file_name> or at least at the first call if you know it will be first time calling.