加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – Rails5 ActionCable与对话聊天

发布时间:2020-12-17 03:10:25 所属栏目:百科 来源:网络整理
导读:根据DHHs Rails5 ActionCable聊天示例,我将创建另一个带有对话和许多消息的示例: rails g model conversation class Conversation ApplicationRecord has_many :messagesendrails g model message content:text conversation:references 视图/会话/ show.ht
根据DHHs Rails5 ActionCable聊天示例,我将创建另一个带有对话和许多消息的示例:

rails g model conversation 

class Conversation < ApplicationRecord
  has_many :messages
end

rails g model message content:text conversation:references

视图/会话/ show.html.erb

<h1>Conversation</h1>

<div id="messages">
  <%= render @messages %>
</div>

<form>
  <label>Say something:</label><br>
  <input type="text" data-behavior="conversation_speaker">
</form>

视图/消息/ _message.html.erb

<div class="message">
  <p><%= message.content %></p>
</div>

我的问题是如何编写一个通道逻辑,将与其对话相关的每条消息写入数据库:

首先,我在控制台上录制了一个对话和一条消息

Conversation.create
Message.create(conversation_id: '1',content: 'hello')

之后我创造了一份工作

rails g job MessageBroadcast

class MessageBroadcastJob < ApplicationJob
  queue_as :default

  render_message(message)
  def perform(data)
    message = Message.create! content: data
    ActionCable.server.broadcast 'conversation_channel',message: render_message(message)
  end

  private
    def render_message(message)
      ApplicationController.renderer.render(partial: 'messages/message',locals: { message: message })
    end
end

和一个频道

rails g channel conversation speak

资产/ Javascript角/信道/ conversation.coffee

App.conversation = App.cable.subscriptions.create "ConversationChannel",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
    $('#messages').append data['message']

  speak: ->
    @perform 'speak'

$(document).on 'keypress','[data-behavior~=conversation_speaker]',(event) ->
  if event.keyCode is 13 # return = send
    App.conversation.speak event.target.value
    event.target.value = ""
    event.preventDefault()

如果我写:

信道/ conversation_channel.rb

class ConversationChannel < ApplicationCable::Channel
  def subscribed
    stream_from "conversation_channel"
  end

  def speak
    Message.create! content: data['message']
  end
end

我明白了

Started GET "/cable/" [WebSocket] for ::1 at 2016-04-22 00:22:13 +0200
Successfully upgraded to WebSocket (REQUEST_METHOD: GET,HTTP_CONNECTION: keep-a
live,Upgrade,HTTP_UPGRADE: websocket)
Started GET "/cable" for ::1 at 2016-04-22 00:22:13 +0200
Started GET "/cable/" [WebSocket] for ::1 at 2016-04-22 00:22:13 +0200
Successfully upgraded to WebSocket (REQUEST_METHOD: GET,HTTP_UPGRADE: websocket)
ConversationChannel is transmitting the subscription confirmation
ConversationChannel is streaming from conversation_channel
ConversationChannel is transmitting the subscription confirmation
ConversationChannel is streaming from conversation_channel

看起来没问题,但如果我在文本字段中输入一些文本并点击返回,我得到:

Could not execute command from {"command"=>"message","identifier"=>"{"channel":"ConversationChannel"}","data"=>"{"action":"speak"}"}) 
[NameError - undefined local variable or method `data' for #<ConversationChannel:0x00000008ad3100>]: 
C:/Sites/ActionCable/app/channels/conversation_channel.rb:13:
in `speak' | C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/actioncable-5.0.0.beta3/lib/action_cable/channel/base.rb:253:
in `public_send' | C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/actioncable-5.0.0.beta3/lib/action_cable/channel/base.rb:253:
in `dispatch_action' | C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/actioncable-5.0.0.beta3/lib/action_cable/channel/base.rb:163:
in `perform_action' | C:/Ruby22-x64/lib/ruby/gems/2.2.0/gems/actioncable-5.0.0.beta3/lib/action_cable/connection/subscriptions.rb:49:
in `perform_action'

有任何想法吗?

解决方法

从客户端到服务器端,您必须(首先)使您的发言功能接受消息参数并将该消息作为JSON对象发送到服务器.

speak: (message) ->
  @perform 'speak',message: message

其次,您必须在channels / conversation_channel.rb中定义通过speak函数接收的参数.因此,您必须将其重新定义为:

def speak(data)
  Message.create! content: data['message']
end

现在你的speak方法正在接收一个数据参数,它是一个带有message属性的JSON,其中包含发送给服务器的消息.它被记录到数据库中,但订阅该频道的人没有答案.

因此,我们必须通知他们重新定义上述方法:

def speak(data)
  Message.create! content: data['message']
  ActionCable.server.broadcast 'conversation_channel',message: render_message(message)
end

private

def render_message(message)
  ApplicationController.renderer.render(partial: 'messages/message',locals: { message: message })
end

现在它应该工作.你在后台做什么取决于你;)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读