Question

I have a Rails app that repeatedly talks to another Web server through a wrapper, and I'd like to stick the wrapper in a Singleton class so it's not recreated for every request. Easy enough, I thought:

class AppWrapper < Wrapper
  include Singleton
end
...
wrapper = AppWrapper.instance "url"

Only it doesn't work:

wrong number of arguments (0 for 1)
/usr/lib/ruby/1.8/singleton.rb:94:in `initialize'
/usr/lib/ruby/1.8/singleton.rb:94:in `new'
/usr/lib/ruby/1.8/singleton.rb:94:in `instance'

Wrapper.initialize needs an argument, and apparently it's not getting passed through, since line 94 in question says

@__instance__ = new # look Ma, no argument

How do I work around this? Redefining initialize in AppWrapper doesn't seem to help, and mucking around with Wrapper to separate "set URL" from "initialize" seems suboptimal.

Was it helpful?

Solution 3

I asked this question while I was still getting my head around Ruby, and it seems so naive now. The easy solution is to just store the Wrapper object in a member variable and use ||= to initialize it only if it hasn't been set yet:

class WrapperUserClass
  def initialize
     @wrapper = nil # Strictly speaking unnecessary, but it's a bit clearer this way
  end

  def wrapper
    @wrapper ||= Wrapper.new(foobar)
  end

  def do_something
    wrapper.booyakasha
  end
end

OTHER TIPS

Passing argument to singleton

class Parameterized_Singleton

def initialize(a)
  @pdf = a
  puts @pdf
end

def self.instance(p)

  begin
    @@instance  =Parameterized_Singleton.new(p)
    private_class_method :new
    rescue NoMethodError
     # return @@instance  # or you can return previous object
      puts "Object Already Created"
      exit
  end

  return @@instance
end

def scanwith(b)
  puts "scan"
end

def show_frequence_distribution
  puts "fd"
end

def show_object_number(a)
  puts "no"
end


end


Parameterized_Singleton.instance(20).show_object_number(10)
Parameterized_Singleton.instance(10).show_object_number(20)

Are you sure you need a singleton and not a factory . Refer this

Since you mention something about editing Wrapper as a solution, can't you just use Wrapper directly and do this?

class Wrapper; include Singleton; end

If not, you could use something like this, which will just make sure AppWrapper.new isn't called more than once:

class AppWrapper
  def self.new(*args)
    class << app_wrapper = Wrapper.new(*args)
      include Singleton
    end
    app_wrapper
  end
end

If you need the singleton "Klass.instance" method, you'll have to take either take out the parameter in Wrapper#initialize, or just redefine Singleton#instance to take arguments optionally and passes them to the call to new on line 94.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top