Wisper: отмена подписки GlobalListeners между запросами
Я хочу зарегистрировать глобальный слушатель в моем ApplicationController, который содержит current_user. Я закончил тем, что попробовал это:
class ApplicationController < ActionController::Base
before_action do
@listener = MyListener.new(current_user)
Wisper.clear if Rails.env.development?
Wisper.subscribe(@listener, scope: :MyPublisher)
end
end
Однако, когда я развернул этот код на heroku, эти глобальные слушатели никогда не отписываются, и приложение продолжает накапливать слушателей через запросы. Я не могу рассчитывать на after_action, поскольку приложение может завершиться из-за ошибки. Как правильно сделать это, это принудительно очистить перед подпиской, вот так?
class ApplicationController < ActionController::Base
before_action do
@listener = MyListener.new(current_user)
Wisper.clear
Wisper.subscribe(@listener, scope: :MyPublisher)
end
end
В другом вопросе Крис предложил использовать инициализатор, который подписывается один раз. Причина, по которой я этого не делаю, заключается в том, что я хочу получить доступ к current_user и предпочитаю не передавать его через глобальные переменные /Thread.current. Каков наилучший способ заставить GlobalListeners работать с current_user?
Мой пример использования - обработка всех экземпляров моделей ActiveRecord, загруженных current_user, во всех действиях контроллера. Виспер делает именно то , что мне было нужно, за исключением упомянутой проблемы.
class MyPublisher < ActiveRecord::Base
include Wisper::Publisher
after_find { broadcast(:process_find, self) }
end
и для слушателя:
class MyListener
def initialize(current_user)
@current_user = current_user
end
def process_find
...
end
end
1 ответ
Вы можете подписать своего слушателя глобально на время блока:
def show
Wisper.subscribe(MyListener.new(current_user)) do
@model = MyPublisher.find(id)
end
end
Слушатель будет отписан по окончании блока.
Если вы хотите, чтобы это произошло более чем за одно действие, вы можете использовать around_action
фильтр:
around_action :subscribe_listener
def show
@model = MyPublisher.find(id)
end
def create
# ...
end
# etc.
private
def subscribe_listener
Wisper.subscribe(MyListener.new(current_user)) do
yield
end
end