Как создать одноэлементный глобальный объект в рельсах
У меня есть объект, который я хочу создать один раз и доступен в одной из моих моделей. Где я его положил? Боюсь, если я поместил его в файл класса модели, он будет создан каждый раз, когда я создам новый экземпляр этой модели. Я только хочу, чтобы этот объект был создан один раз при запуске. Здесь объект:
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)
Я использую его вот так в модели:
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
Ответы
Ответ 1
В Rails объекты воссоздаются по каждому запросу. Если это какая-то услуга, она должна быть одиночной в рамках запроса.
Объекты Singleton должны быть созданы с помощью однослойного mixin ruby:
require 'singleton'
class Pubnub
include Singleton
def initialize(publish_key, subscribe_key, secret_key, ssl_on)
# ...
end
def publish
# ...
end
end
Затем вы можете вызвать его с помощью метода instance
:
Pubnub.instance.publish
Таким образом вы убедитесь, что этот объект будет на самом деле одиночным (только один экземпляр будет существовать).
Вы можете безопасно разместить его в каталоге models
, хотя я часто предпочитаю каталог lib
или, возможно, создаю новый каталог для служб. Это зависит от ситуации.
Надеюсь, что это поможет!
Ответ 2
Если вам нужен только один экземпляр во всем приложении, используйте одноэлемент, иначе используйте переменную класса.
Чтобы использовать один синглтон, включите микширование Singleton.
require 'singleton'
class Pubnub
include Singleton
attr_writer :publish_key, :subscribe_key, :secret_key, :ssl_on
def publish
#...
end
end
а затем используйте его следующим образом:
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
Вы также можете сделать его переменной класса, чтобы связать его более тесно с определенной моделью:
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