0

current_user を含むグローバル リスナーを ApplicationController に登録したいと考えています。私はこれを試してみました:

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

別の質問で、Kris は 1 回サブスクライブするイニシャライザを使用する必要があると提案しました。私がこれを行っていない理由は、current_user にアクセスしたいからであり、グローバル変数/Thread.current 経由で渡したくないからです。GlobalListeners を 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
4

1 に答える 1

0

ブロックの期間中、リスナーをグローバルにサブスクライブできます。

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
于 2016-05-12T08:33:05.473 に答える