Wisper:在请求之间取消订阅GlobalListeners

时间:2016-05-11 08:04:24

标签: ruby-on-rails wisper

我想在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

在另一个question中,Kris建议我们应该使用一次订阅的初始化程序。我不这样做的原因是因为我想访问current_user,我不想通过全局变量/ Thread.current传递它。使GlobalListener与current_user一起工作的最佳方法是什么?

我的用例是在所有控制器操作中处理由current_user加载的ActiveRecord模型的所有实例。除了提到的问题,Wisper确实完全我需要它做什么。

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 个答案:

答案 0 :(得分:0)

您可以订阅您的听众globally for the duration of a block

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