2012-05-25 10 views
20

Tengo un objeto que quiero crear una vez y accesible en uno de mis modelos. ¿Dónde lo pongo? Me temo que si lo incluyo en el archivo de la clase de modelo, lo crearán cada vez que haga una nueva instancia de ese modelo. Solo quiero que este objeto se cree una vez al inicio. Aquí está el objeto:cómo puedo crear un objeto global singleton en rieles

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) 

lo utilizo como este en el modelo:

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 
+0

creo que se puede también use una variable global, vea este ejemplo aquí: https://github.com/pubnub/ruby/blob/master/examples/pubnub_livestream/config/initializers/pubnub.rb –

Respuesta

31

En los carriles, los objetos se vuelven a crear en cada petición. Si se trata de algún tipo de servicio, debe ser un singleton en el ámbito de una solicitud.

objetos Singleton deben ser creados con el mixin rubí Singleton:

require 'singleton' 

class Pubnub 
    include Singleton 

    def initialize(publish_key, subscribe_key, secret_key, ssl_on) 
    # ... 
    end 

    def publish 
    # ... 
    end 
end 

Entonces se le puede llamar con el instance método:

Pubnub.instance.publish 

De esta manera se asegura de que este objeto será en realidad un singleton (solo existirá una instancia).

Puede colocarlo de forma segura en el directorio models, aunque a menudo prefiero el directorio lib o tal vez cree un nuevo directorio para servicios. Depende de la situación.

Espero que ayude!

+0

Para el registro, la primera afirmación solo es verdadera si el config.cache_classes es establecer en falso Lo cual es, por defecto, no verdadero en Producción. No sé cuál es el comportamiento con Singleton mixin. – Michael

+1

Existe un peligro potencial en este enfoque cuando se utiliza un servidor multiproceso como Phusion Passenger. PP crea un hilo por solicitud y, además, estos hilos probablemente existirán en procesos separados, por lo que cada proceso tendrá su propio objeto singleton compartido por varios hilos de este proceso. – Paul

+0

para extender el comentario anterior de Paul, tenga en cuenta que también hay un problema si no desea que se comparta, ya que el deseo es tener un singleton por solicitud. http://stackoverflow.com/questions/24927928/singleton-in-scope-of-a-request-in-rails – futbolpal

2

Si solo desea una instancia en toda su aplicación, use una sola tecla; de lo contrario, use una variable de clase.

Para usar un singleton, incluya la mezcla de Singleton.

require 'singleton' 

class Pubnub 
    include Singleton 

    attr_writer :publish_key, :subscribe_key, :secret_key, :ssl_on 

    def publish 
    #... 
    end 
end 

y luego usarlo como esto:

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 

También podría hacer que sea una variable de clase, para vincularla más estrechamente a un modelo específico:

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 
Cuestiones relacionadas