30

I have an object that I want created once and accessible in one of my models. Where do I put him? I'm afraid if I put him in the model class file he'll get created every time I make a new instance of that model. I only want this object created once at start up. Here's the object:

require 'pubnub' publish_key = 'fdasfs' subscribe_key = 'sdfsdsf' secret_key = 'fsdfsd' ssl_on = false pubnub_obj = Pubnub.new(publish_key, subscribe_key, secret_key, ssl_on) 

I use him like this in the model:

class Message < ActiveRecord::Base def self.send_new_message_client(message) message = { 'some_data' => message } info = pubnub_obj.publish({ 'channel' => 'testing', 'message' => message }) puts(info) end end 
2

2 Answers 2

41

In Rails, objects are recreated on each request. If this is some kind of service, it should be a singleton in the scope of a request.

Singleton objects should be created with the ruby singleton mixin:

require 'singleton' class Pubnub include Singleton def initialize(publish_key, subscribe_key, secret_key, ssl_on) # ... end def publish # ... end end 

Then you can call it with the instance method:

Pubnub.instance.publish 

This way you make sure that this object will actually be a singleton (only one instance will exist).

You can place it safely in the models directory, though I often prefer the lib directory or maybe create a new directory for services. It depends on the situation.

Hope it helps!

Sign up to request clarification or add additional context in comments.

3 Comments

For the record, the first statement is only true if the config.cache_classes is set to false. Which is, by default, not true in Production. I don't know what the behavior is with the Singleton mixin.
There is a potential danger in this approach when using some multi-process server like Phusion Passenger. PP creates one thread per request and moreover - these threads will be likely to exist in separate processes, so each process will have it's own singleton object shared by multiple threads of this process.
to extend Paul's comment above, be aware there is also an issue if you don't want it shared, in that the desire is to have a singleton per request. stackoverflow.com/questions/24927928/…
5

If you want only one instance in your whole application, use a singleton, otherwise use a class variable.

To use a singleton, include the Singleton mixin.

require 'singleton' class Pubnub include Singleton attr_writer :publish_key, :subscribe_key, :secret_key, :ssl_on def publish #... end end 

and then use it like this:

require 'pubnub' class Message < ActiveRecord::Base Pubnub.instance.publish_key = 'xyz' Pubnub.instance.subscribe_key = 'xyz' Pubnub.instance.secret_key = 'xyz' Pubnub.instance.ssl_on = 'xyz' def self.send_new_message_client(message) message = { 'some_data' => message } info = Pubnub.instance.publish({ 'channel' => 'testing', 'message' => message }) puts(info) end end 

You could also make it a class variable, to link it more tightly to a specific model:

require 'pubnub' class Message < ActiveRecord::Base @@pubnub_obj = Pubnub.new('xyz', 'xyz', 'xyz', 'xyz') def self.send_new_message_client(message) message = { 'some_data' => message } info = @@pubnub_obj.publish({ 'channel' => 'testing', 'message' => message }) puts(info) end end 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.