4

일부 사용자 속성에 따라 사용자를 특정 채널에 가입 시킬지 여부를 결정하는 코드가 application.html.haml에 있습니다.레일 액션 케이블 및 터보 링크 : 다중 바인딩 방지

내가 본문에서이 코드 조각을 가지고 있으면 다른 페이지로 리디렉션되는 링크를 클릭하면 이전 연결을 유지하는 대신 사용자가 다시 구독하므로 메서드가 있습니다. 여러 번 실행됩니다.

%html 
    %head 
    -# other stuff 
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' 
    %body 
    -# other stuff 

    - if current_user.is_admin? 
     :coffee 
     MyApp.AdminNotifications.init() 

자산/자바 스크립트/통지/admin_notifications.js.coffee

window.MyApp.AdminNotifications = class AdminNotifications 
    @init: -> 
    App.cable.subscriptions.create "ProductsChannel", 
     received: (data) -> 
     console.log 'Data Received' # This is being executed multiple times 

페이지가로드 처음으로, 나는 방송 때

이것은 application.html.haml 내 코드입니다 메시지를 해당 채널에 보내면 콘솔에서 "Data Received"를 한 번만 기록합니다. 링크를 클릭하여 다른 페이지로 리디렉션하고 해당 채널에 새 메시지를 브로드 캐스트합니다. 이제 콘솔에 "데이터 수신"이 두 번 기록됩니다. 그리고 지금까지 등등 ...

사실

, 나는 크롬의 콘솔에서 실행하면 내가 링크를 클릭 얻은마다 한 번씩 (동일한 채널에 여러 구독을 반환

App.cable.subscriptions.subscriptions 

다른 페이지로 리디렉션 됨).

참고 : 제대로 작동하기 때문에이 게시물에 추가하지 않을 조치 케이블 설정이 더 있습니다.

어떻게 피할 수 있습니까? 어떤 아이디어?

답변

0

그것은 보이는, 그래서 당신은 클래스가 초기화 된 플래그 클래스 속성을 추가해야 할 수 있습니다 : 당신이 할 수있다 미래에

window.MyApp.AdminNotifications = class AdminNotifications 
    @init: -> 
    unless @initialized 
     App.cable.subscriptions.create "ProductsChannel", 
     received: (data) -> 
      console.log 'Data Received' 
     @initialized = true 

을 자신의 가입을 관리하기 위해 Action Cable API를 포장하고 싶습니다.

일반적으로

Turbolinks 작업, 당신의 application.js 인라인 스크립트 (: https://github.com/rails/rails/pull/23012#issue-125970208 참조)이 아닌 파일에 가능한 한 많은 물건을 포함하는 것이 바람직하다. 조건부로 실행할 수 있도록 인라인 스크립트를 사용했다고 생각합니다 (if current_user.is_admin?). 인기있는 방법은이 데이터를 전달하기 위해 메타 태그를 사용하는 것입니다, 그래서 당신의 머리에 :

window.MyApp.User = class User 
    constructor: -> 
    @isAdmin = @getMeta('current-user-is-admin') == 'true' 

    getMeta: (name) -> 
    meta = document.querySelector("meta[name=#{name}]") 
    meta.getAttribute('content') if meta 

을 마지막으로 포함 레이아웃에서 AdminNotifications 초기화 코드를 제거 :

<meta name="current-user-is-admin" content="true"> 

그런 다음 당신은 할 수 있습니다 귀하의 애플리케이션 어딘가에 있습니다.

document.addEventListener('turbolinks:load', -> 
    window.MyApp.currentUser = new window.MyApp.User 
    window.MyApp.AdminNotifications.init() if window.MyApp.currentUser.isAdmin 
) 

희망 하시겠습니까?

+0

현상금에 감사드립니다! 문제를 해결하기 위해이 답변을 찾은 경우 "수락"으로 표시하십시오. 다시 한번 감사드립니다 :) –

0

신체 대신 머리에 쓰는 것이 어떻습니까? 이벤트가 터보 링크에 의해 여러 번 등록되었을 수 있습니다. 당신은 단지 MyApp.AdminNotifications의 단일 인스턴스를 원하는처럼

%html 
    %head 
    -# other stuff 
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' 

    - if current_user.is_admin? 
     :coffee 
     MyApp.AdminNotifications.init() 

    %body 
    -# other stuff 
관련 문제