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 现在它应该工作.你在后台做什么取决于你;) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |