Ruby on rails Rails如何使用ActionCable在;收到:“;

Ruby on rails Rails如何使用ActionCable在;收到:“;,ruby-on-rails,coffeescript,actioncable,Ruby On Rails,Coffeescript,Actioncable,我正在尝试制作一个具有2种用户类型的测验应用程序(非单页应用程序),该用例: 测验主持人用户和参与者用户处于“等待”状态 直到测验开始 测验主持人用户点击“测验开始”按钮开始测验 这会立即强制所有参与者用户重定向到包含测验问题的新页面 我按照教程在我的应用程序中设置了ActionCable,但我想知道的是如何实现步骤3。我当前频道的咖啡脚本文件如下所示: # \app\assets\javascripts\channels\quiz_data.coffee: App.quiz_data = Ap

我正在尝试制作一个具有2种用户类型的测验应用程序(非单页应用程序),该用例:

  • 测验主持人用户和参与者用户处于“等待”状态 直到测验开始
  • 测验主持人用户点击“测验开始”按钮开始测验
  • 这会立即强制所有参与者用户重定向到包含测验问题的新页面
  • 我按照教程在我的应用程序中设置了ActionCable,但我想知道的是如何实现步骤3。我当前频道的咖啡脚本文件如下所示:

    # \app\assets\javascripts\channels\quiz_data.coffee:
    App.quiz_data = App.cable.subscriptions.create "QuizDataChannel",
      connected: ->
        # Called when the subscription is ready for use on the server
    
      disconnected: ->
        # Called when the subscription has been terminated by the server
    
      received: (data) ->
        # Called when there's incoming data on the websocket for this channel
        if current_student
          # HERE I want to render the page "quiz_question.html.erb"
    
          # ...and then I want to append the answer buttons:
          $('answer-buttons').append(data.partial)
    
      send_data: ->
        @perform 'send_data'
    
    我很确定答案很简单,但我在谷歌上搜索了很多Coffeescript和ActionCable教程,几乎所有的教程都只在用户已经在的页面上呈现部分内容。我是一个Rails初学者,对Coffeescript一无所知,因此任何帮助都将不胜感激

    编辑:

    这就是我的coffeescript文件在尝试遵循Laiths答案后的样子:

    App.quiz_data = App.cable.subscriptions.create "QuizDataChannel",
      connected: ->
        # Called when the subscription is ready for use on the server
        $('#btn btn-primary btn-lg').on 'click', (e) -> App.quiz_data.send_data()
    
      disconnected: ->
        # Called when the subscription has been terminated by the server
    
      received: (data) ->
        # Called when there's incoming data on the websocket for this channel
        if current_student
          pageHtml = data.page_html
          answerHtml = data.answer_html
    
          # This will replace your body with the page html string:
          $('body').html(pageHtml)
    
          # Then add your answer buttons:
          #$('#answer-buttons').html(answerHtml)
          $('answer-buttons').append(answerHtml)
    
      send_data: ->
        @perform 'send_data'
    
    这是我创造的工作,用来呈现我的片段并广播它们:

    # app\assets\jobs\quiz_data_broadcast_job.rb:
    class QuizDataBroadcastJob < ApplicationJob
      queue_as :default
    
      def perform(answers)
        ActionCable.server.broadcast('quiz_data', {
            page_html: render_page,
            answer_html: render_answer_options(answers)
        })
      end
    
      private
      def render_page
        ApplicationController.render(
            partial: 'pages/student/quiz_question',
            locals: {}
        )
      end
    
      def render_answer_options(answers)
        answers.each do |answer|
          ApplicationController.render(
              #render student/quiz_question page and render as many answer_option partials as needed
              partial: 'pages/student/answer_option',
              locals: {answer: answer}
          )
        end
      end
    end
    
    这是当我点击它时显示的内容:

    1    (function() {
    2      App.quiz_data = App.cable.subscriptions.create("QuizDataChannel", {
    3        connected: function() {
    4          return $('#btn btn-primary btn-lg').on('click', function(e) {
    5            return App.quiz_data.send_data();
    6          });
    7        },
    8        disconnected: function() {},
    9        received: function(data) {
    10         var answerHtml, pageHtml;
    11         if (current_student) {
    12           pageHtml = data.page_html;
    13           answerHtml = data.answer_html;
    14           $('body').html(pageHtml);
    15           return $('answer-buttons').append(answerHtml);
    16         }
    17       },
    18       send_data: function() {
    19         return this.perform('send_data');
    20       }
    21     });
    22    
    23   }).call(this);
    
    编辑3: 这是我的cable.js:

    // Action Cable provides the framework to deal with WebSockets in Rails.
    // You can generate new channels where WebSocket features live using the rails generate channel command.
    //
    //= require action_cable
    //= require_self
    //= require_tree ./channels
    
    (function() {
      this.App || (this.App = {});
    
      App.cable = ActionCable.createConsumer();
    
    }).call(this);
    

    WebSocket并不是真正设计用来执行HTTP重定向的。但是,您仍然可以通过一些jQuery给人一种页面已经改变的感觉

    由于在主持人单击“开始”后,您将同时创建问题和答案,因此您可以在广播中发送这两个问题和答案

    首先,我建议将
    quick\u question.html.erb
    文件更改为部分:
    \u quick\u question.html.erb
    ,以便生成html并将其附加到身体中。接下来,将
    答案按钮
    元素包含在您的_quick_问题文件中,这样您就可以用jquery抓取它了

    因此,它看起来与此类似,但会因具体实现的不同而有所不同:

    # First create the question HTML partial (ensure this has the answer-
    # buttons element inside it):
    question_html = ApplicationController.render(partial: 
    'quizzes/_quiz_question', locals: {question: @question})
    
    # Next create the answer HTML partial:
    answer_html = ApplicationController.render(partial: 
    'answers/_answe_buttonr', locals: {answer: @answer})
    
    # Broadcast both to your channel:
    ActionCable.server.broadcast('QuizDataChannel', {
      question_html: question_html
      answer_html: answer_html
    })
    
    # Finally, handle this using jquery in your coffeescript:
    received: (data) ->
      questionHtml = data.question_html
      answerHtml = data.answer_html
    
      # This will replace your body with the question html string:
      $('body').html(questionHtml)
    
      # Then add your answer buttons:
      $('#answer-buttons').html(answerHtml)
    

    WebSocket并不是真正设计用来执行HTTP重定向的。但是,您仍然可以通过一些jQuery给人一种页面已经改变的感觉

    由于在主持人单击“开始”后,您将同时创建问题和答案,因此您可以在广播中发送这两个问题和答案

    首先,我建议将
    quick\u question.html.erb
    文件更改为部分:
    \u quick\u question.html.erb
    ,以便生成html并将其附加到身体中。接下来,将
    答案按钮
    元素包含在您的_quick_问题文件中,这样您就可以用jquery抓取它了

    因此,它看起来与此类似,但会因具体实现的不同而有所不同:

    # First create the question HTML partial (ensure this has the answer-
    # buttons element inside it):
    question_html = ApplicationController.render(partial: 
    'quizzes/_quiz_question', locals: {question: @question})
    
    # Next create the answer HTML partial:
    answer_html = ApplicationController.render(partial: 
    'answers/_answe_buttonr', locals: {answer: @answer})
    
    # Broadcast both to your channel:
    ActionCable.server.broadcast('QuizDataChannel', {
      question_html: question_html
      answer_html: answer_html
    })
    
    # Finally, handle this using jquery in your coffeescript:
    received: (data) ->
      questionHtml = data.question_html
      answerHtml = data.answer_html
    
      # This will replace your body with the question html string:
      $('body').html(questionHtml)
    
      # Then add your answer buttons:
      $('#answer-buttons').html(answerHtml)
    

    在主持人点击开始按钮后,您是否同时创建了问题页面和答案按钮?是的,这是计划@Laith在主持人点击开始按钮后,您是否同时创建了问题页面和答案按钮?是的,这是计划@Laith谢谢您的详细建议@Laith。我已经将第一部分(为我的项目定制)集成到连接的
    方法中,将第二部分集成到我的coffeescript文件的
    接收的
    方法中。但现在我得到了一个“未捕获引用错误:未定义应用程序”-在您帮助我之后,我已经从我的Ruby代码中删除了任何调用应用程序的尝试,所以我有点困惑。您是在javascript控制台还是服务器日志中得到这个消息的?javascript console@laith这是您应该调用
    应用程序的正确位置。(在你的咖啡脚本中,它会被转换成javascript)。如果单击它,它是否会显示错误所在?似乎由于某种原因,
    cable.js
    文件没有运行。是项目中的该文件,它是否具有以下内容:
    (function(){this.App | | |(this.App={});App.cable=ActionCable.createConsumer();})?感谢您对@Laith的详细建议。我已经将第一部分(为我的项目定制)集成到连接的
    方法中,将第二部分集成到我的coffeescript文件的
    接收的
    方法中。但现在我得到了一个“未捕获引用错误:未定义应用程序”-在您帮助我之后,我已经从我的Ruby代码中删除了任何调用应用程序的尝试,所以我有点困惑。您是在javascript控制台还是服务器日志中得到这个消息的?javascript console@laith这是您应该调用
    应用程序的正确位置。(在你的咖啡脚本中,它会被转换成javascript)。如果单击它,它是否会显示错误所在?似乎由于某种原因,
    cable.js
    文件没有运行。是项目中的该文件,它是否具有以下内容:
    (function(){this.App | | |(this.App={});App.cable=ActionCable.createConsumer();})